1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "template_cache_manager.h"
17
18 #include <mutex>
19
20 #include "os_account_manager.h"
21 #include "iservice_registry.h"
22 #include "system_ability_definition.h"
23 #include "system_ability_status_change_stub.h"
24
25 #include "iam_check.h"
26 #include "iam_logger.h"
27 #include "iam_ptr.h"
28 #include "context_pool.h"
29 #include "resource_node_pool.h"
30 #include "resource_node_utils.h"
31 #include "user_idm_database.h"
32 #include "thread_handler.h"
33
34 #define LOG_TAG "USER_AUTH_SA"
35 namespace OHOS {
36 namespace UserIam {
37 namespace UserAuth {
38 namespace {
GetCurrentUserId()39 int32_t GetCurrentUserId()
40 {
41 std::vector<int32_t> ids;
42 ErrCode queryRet = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
43 if (queryRet != ERR_OK || ids.empty()) {
44 IAM_LOGE("failed to query active account id ret %{public}d count %{public}zu",
45 queryRet, ids.size());
46 return INVALID_USER_ID;
47 }
48 return ids.front();
49 }
50 }
51 using OsAccountSubscriber = AccountSA::OsAccountSubscriber;
52 using OsAccountSubscribeInfo = AccountSA::OsAccountSubscribeInfo;
53 using OS_ACCOUNT_SUBSCRIBE_TYPE = AccountSA::OS_ACCOUNT_SUBSCRIBE_TYPE;
54
55 class ServiceStatusListener : public OHOS::SystemAbilityStatusChangeStub, public NoCopyable {
56 public:
57 static sptr<ServiceStatusListener> GetInstance();
58 static void Subscribe();
59
60 void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override;
61 void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override;
62
63 private:
ServiceStatusListener()64 ServiceStatusListener() {};
~ServiceStatusListener()65 ~ServiceStatusListener() override {};
66 };
67
68 class OsAccountIdSubscriber : public OsAccountSubscriber, public NoCopyable {
69 public:
70 explicit OsAccountIdSubscriber(const OsAccountSubscribeInfo &subscribeInfo);
71 ~OsAccountIdSubscriber() = default;
72
73 static std::shared_ptr<OsAccountIdSubscriber> GetInstance();
74 static void Subscribe();
75 static void Unsubscribe();
76 void OnAccountsChanged(const int& id) override;
77
78 private:
79 std::shared_ptr<ThreadHandler> threadHandler_;
80 };
81
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)82 void ServiceStatusListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
83 {
84 if (systemAbilityId != SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) {
85 return;
86 }
87
88 IAM_LOGI("os account service added");
89 OsAccountIdSubscriber::Subscribe();
90 IAM_LOGI("os account service add process finish");
91 }
92
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)93 void ServiceStatusListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
94 {
95 if (systemAbilityId != SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) {
96 return;
97 }
98
99 IAM_LOGI("os account service removed");
100 OsAccountIdSubscriber::Unsubscribe();
101 ContextPool::Instance().CancelAll();
102 IAM_LOGI("os account service remove process finish");
103 }
104
GetInstance()105 sptr<ServiceStatusListener> ServiceStatusListener::GetInstance()
106 {
107 static sptr<ServiceStatusListener> listener(new (std::nothrow) ServiceStatusListener());
108 if (listener == nullptr) {
109 IAM_LOGE("ServiceStatusListener is null");
110 }
111 return listener;
112 }
113
Subscribe()114 void ServiceStatusListener::Subscribe()
115 {
116 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
117 if (sam == nullptr) {
118 IAM_LOGE("failed to get SA manager");
119 return;
120 }
121
122 auto instance = GetInstance();
123 IF_FALSE_LOGE_AND_RETURN(instance != NULL);
124
125 int32_t ret = sam->SubscribeSystemAbility(SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN, instance);
126 if (ret != ERR_OK) {
127 IAM_LOGE("failed to subscribe os account service status");
128 return;
129 }
130
131 IAM_LOGI("subscribe os account SA service status success");
132 }
133
OsAccountIdSubscriber(const OsAccountSubscribeInfo & subscribeInfo)134 OsAccountIdSubscriber::OsAccountIdSubscriber(const OsAccountSubscribeInfo &subscribeInfo)
135 : OsAccountSubscriber(subscribeInfo),
136 threadHandler_(ThreadHandler::GetSingleThreadInstance())
137 {}
138
Subscribe()139 void OsAccountIdSubscriber::Subscribe()
140 {
141 IAM_LOGI("start");
142 auto instance = GetInstance();
143 IF_FALSE_LOGE_AND_RETURN(instance != NULL);
144
145 ErrCode errCode = AccountSA::OsAccountManager::SubscribeOsAccount(instance);
146 if (errCode != ERR_OK) {
147 IAM_LOGE("subscribe fail, errCode = %{public}d", errCode);
148 return;
149 }
150
151 int32_t userId = GetCurrentUserId();
152 if (userId == INVALID_USER_ID) {
153 IAM_LOGE("GetCurrentUserId fail");
154 return;
155 }
156 TemplateCacheManager::GetInstance().ProcessUserIdChange(userId);
157 IAM_LOGI("subscribe success");
158 }
159
Unsubscribe()160 void OsAccountIdSubscriber::Unsubscribe()
161 {
162 auto instance = GetInstance();
163 IF_FALSE_LOGE_AND_RETURN(instance != NULL);
164
165 ErrCode errCode = AccountSA::OsAccountManager::UnsubscribeOsAccount(instance);
166 if (errCode != ERR_OK) {
167 IAM_LOGE("unsubscribe fail, errCode = %{public}d", errCode);
168 return;
169 }
170 IAM_LOGI("unsubscribe success");
171 }
172
OnAccountsChanged(const int & id)173 void OsAccountIdSubscriber::OnAccountsChanged(const int& id)
174 {
175 IAM_LOGI("OnAccountsChanged %{public}d", id);
176 if (threadHandler_ == nullptr) {
177 IAM_LOGE("threadHandler_ not set");
178 return;
179 }
180
181 threadHandler_->PostTask([id]() {
182 IAM_LOGI("task process begin");
183 TemplateCacheManager::GetInstance().ProcessUserIdChange(id);
184 IAM_LOGI("task process end");
185 });
186 }
187
GetInstance()188 std::shared_ptr<OsAccountIdSubscriber> OsAccountIdSubscriber::GetInstance()
189 {
190 OsAccountSubscribeInfo subscribeInfo;
191 subscribeInfo.SetOsAccountSubscribeType(OS_ACCOUNT_SUBSCRIBE_TYPE::ACTIVED);
192
193 static auto subscriber = Common::MakeShared<OsAccountIdSubscriber>(subscribeInfo);
194 if (subscriber == nullptr) {
195 IAM_LOGE("OsAccountIdSubscriber is null");
196 }
197 return subscriber;
198 }
199
TemplateCacheManager()200 TemplateCacheManager::TemplateCacheManager()
201 {
202 ServiceStatusListener::Subscribe();
203 }
204
GetInstance()205 TemplateCacheManager &TemplateCacheManager::GetInstance()
206 {
207 static TemplateCacheManager templateCacheManager;
208 return templateCacheManager;
209 }
210
ProcessUserIdChange(const int newUserId)211 void TemplateCacheManager::ProcessUserIdChange(const int newUserId)
212 {
213 {
214 std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
215 if (newUserId == currUserId_) {
216 IAM_LOGE("same userId %{public}d", newUserId);
217 return;
218 }
219
220 IAM_LOGI("begin");
221 currUserId_ = newUserId;
222 }
223 UpdateTemplateCache(FACE);
224 UpdateTemplateCache(FINGERPRINT);
225 IAM_LOGI("done");
226 return;
227 }
228
UpdateTemplateCache(AuthType authType)229 void TemplateCacheManager::UpdateTemplateCache(AuthType authType)
230 {
231 IAM_LOGI("start");
232 int32_t currUserId = 0;
233 {
234 std::lock_guard<std::recursive_mutex> lock(recursiveMutex_);
235 currUserId = currUserId_;
236 }
237
238 IF_FALSE_LOGE_AND_RETURN(currUserId != INVALID_USER_ID);
239 if (authType != FACE && authType != FINGERPRINT) {
240 IAM_LOGI("this auth type is not cached");
241 return;
242 }
243
244 std::vector<std::shared_ptr<CredentialInfoInterface>> credentialInfos;
245 int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(currUserId, authType, credentialInfos);
246 if (ret != SUCCESS) {
247 IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
248 currUserId, authType);
249 return;
250 }
251
252 if (credentialInfos.empty()) {
253 IAM_LOGI("user %{public}d has no credential type %{public}d", currUserId, authType);
254 ResourceNodePool::Instance().Enumerate([authType](const std::weak_ptr<ResourceNode> &node) {
255 auto nodeTmp = node.lock();
256 IF_FALSE_LOGE_AND_RETURN(nodeTmp != nullptr);
257
258 if (nodeTmp->GetAuthType() != authType) {
259 return;
260 }
261 IAM_LOGI("clear cached template for type %{public}d", authType);
262 ResourceNodeUtils::SetCachedTemplates(nodeTmp->GetExecutorIndex(),
263 std::vector<std::shared_ptr<CredentialInfoInterface>>());
264 });
265 return;
266 }
267
268 IAM_LOGI("user %{public}d type %{public}d credential info size %{public}zu",
269 currUserId, authType, credentialInfos.size());
270 std::map<uint64_t, std::vector<std::shared_ptr<CredentialInfoInterface>>> id2Cred;
271 ResultCode result = ResourceNodeUtils::ClassifyCredInfoByExecutor(credentialInfos, id2Cred);
272 IF_FALSE_LOGE_AND_RETURN(result == SUCCESS);
273
274 for (auto const &pair : id2Cred) {
275 ResourceNodeUtils::SetCachedTemplates(pair.first, pair.second);
276 }
277 }
278 } // namespace UserAuth
279 } // namespace UserIam
280 } // namespace OHOS