1 /*
2 * Copyright (c) 2022-2024 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 "token_modify_notifier.h"
17
18 #include "accesstoken_callback_proxys.h"
19 #include "accesstoken_id_manager.h"
20 #include "accesstoken_info_manager.h"
21 #include "accesstoken_common_log.h"
22 #include "access_token_error.h"
23 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
24 #include "ffrt.h"
25 #endif
26 #include "hap_token_info.h"
27 #include "hap_token_info_inner.h"
28 #include "libraryloader.h"
29 #include "token_sync_kit_loader.h"
30
31 namespace OHOS {
32 namespace Security {
33 namespace AccessToken {
34 namespace {
35 std::recursive_mutex g_instanceMutex;
36 }
37
38 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
TokenModifyNotifier()39 TokenModifyNotifier::TokenModifyNotifier() : hasInited_(false), curTaskNum_(0) {}
40 #else
TokenModifyNotifier()41 TokenModifyNotifier::TokenModifyNotifier() : hasInited_(false), notifyTokenWorker_("TokenModify") {}
42 #endif
43
~TokenModifyNotifier()44 TokenModifyNotifier::~TokenModifyNotifier()
45 {
46 if (!hasInited_) {
47 return;
48 }
49 #ifndef RESOURCESCHEDULE_FFRT_ENABLE
50 this->notifyTokenWorker_.Stop();
51 #endif
52 this->hasInited_ = false;
53 }
54
AddHapTokenObservation(AccessTokenID tokenID)55 void TokenModifyNotifier::AddHapTokenObservation(AccessTokenID tokenID)
56 {
57 if (AccessTokenIDManager::GetInstance().GetTokenIdType(tokenID) != TOKEN_HAP) {
58 LOGI(ATM_DOMAIN, ATM_TAG, "Observation token is not hap token");
59 return;
60 }
61 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
62 if (observationSet_.count(tokenID) <= 0) {
63 observationSet_.insert(tokenID);
64 }
65 }
66
NotifyTokenDelete(AccessTokenID tokenID)67 void TokenModifyNotifier::NotifyTokenDelete(AccessTokenID tokenID)
68 {
69 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
70 if (observationSet_.count(tokenID) <= 0) {
71 LOGD(ATM_DOMAIN, ATM_TAG, "Hap token is not observed");
72 return;
73 }
74 observationSet_.erase(tokenID);
75 deleteTokenList_.emplace_back(tokenID);
76 NotifyTokenChangedIfNeed();
77 }
78
NotifyTokenModify(AccessTokenID tokenID)79 void TokenModifyNotifier::NotifyTokenModify(AccessTokenID tokenID)
80 {
81 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
82 if (observationSet_.count(tokenID) <= 0) {
83 LOGD(ATM_DOMAIN, ATM_TAG, "Hap token is not observed");
84 return;
85 }
86 modifiedTokenList_.emplace_back(tokenID);
87 NotifyTokenChangedIfNeed();
88 }
89
GetInstance()90 TokenModifyNotifier& TokenModifyNotifier::GetInstance()
91 {
92 static TokenModifyNotifier* instance = nullptr;
93 if (instance == nullptr) {
94 std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
95 if (instance == nullptr) {
96 TokenModifyNotifier* tmp = new TokenModifyNotifier();
97 instance = std::move(tmp);
98 }
99 }
100
101 if (!instance->hasInited_) {
102 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(instance->initLock_);
103 if (!instance->hasInited_) {
104 #ifndef RESOURCESCHEDULE_FFRT_ENABLE
105 instance->notifyTokenWorker_.Start(1);
106 #endif
107 instance->hasInited_ = true;
108 }
109 }
110
111 return *instance;
112 }
113
NotifyTokenSyncTask()114 void TokenModifyNotifier::NotifyTokenSyncTask()
115 {
116 LOGI(ATM_DOMAIN, ATM_TAG, "Called!");
117
118 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
119 LibraryLoader loader(TOKEN_SYNC_LIBPATH);
120 TokenSyncKitInterface* tokenSyncKit = loader.GetObject<TokenSyncKitInterface>();
121 if (tokenSyncKit == nullptr) {
122 LOGE(ATM_DOMAIN, ATM_TAG, "Dlopen libtokensync_sdk failed.");
123 return;
124 }
125 for (AccessTokenID deleteToken : deleteTokenList_) {
126 int ret = TOKEN_SYNC_SUCCESS;
127 if (tokenSyncCallbackObject_ != nullptr) {
128 ret = tokenSyncCallbackObject_->DeleteRemoteHapTokenInfo(deleteToken);
129 }
130 ret = tokenSyncKit->DeleteRemoteHapTokenInfo(deleteToken);
131 if (ret != TOKEN_SYNC_SUCCESS) {
132 LOGE(ATM_DOMAIN, ATM_TAG, "Fail to delete remote haptoken info, ret is %{public}d", ret);
133 }
134 }
135
136 for (AccessTokenID modifyToken : modifiedTokenList_) {
137 HapTokenInfoForSync hapSync;
138 int ret = AccessTokenInfoManager::GetInstance().GetHapTokenSync(modifyToken, hapSync);
139 if (ret != RET_SUCCESS) {
140 LOGE(ATM_DOMAIN, ATM_TAG, "The hap token 0x%{public}x need to sync is not found!", modifyToken);
141 continue;
142 }
143 if (tokenSyncCallbackObject_ != nullptr) {
144 ret = tokenSyncCallbackObject_->UpdateRemoteHapTokenInfo(hapSync);
145 }
146 ret = tokenSyncKit->UpdateRemoteHapTokenInfo(hapSync);
147 if (ret != TOKEN_SYNC_SUCCESS) {
148 LOGE(ATM_DOMAIN, ATM_TAG, "Fail to update remote haptoken info, ret is %{public}d", ret);
149 }
150 }
151 deleteTokenList_.clear();
152 modifiedTokenList_.clear();
153
154 LOGI(ATM_DOMAIN, ATM_TAG, "Over!");
155 }
156
GetRemoteHapTokenInfo(const std::string & deviceID,AccessTokenID tokenID)157 int32_t TokenModifyNotifier::GetRemoteHapTokenInfo(const std::string& deviceID, AccessTokenID tokenID)
158 {
159 if (tokenSyncCallbackObject_ != nullptr) {
160 Utils::UniqueReadGuard<Utils::RWLock> infoGuard(this->Notifylock_);
161 int32_t ret = tokenSyncCallbackObject_->GetRemoteHapTokenInfo(deviceID, tokenID);
162 if (ret != TOKEN_SYNC_OPENSOURCE_DEVICE) {
163 return ret;
164 }
165 }
166
167 LibraryLoader loader(TOKEN_SYNC_LIBPATH);
168 TokenSyncKitInterface* tokenSyncKit = loader.GetObject<TokenSyncKitInterface>();
169 if (tokenSyncKit == nullptr) {
170 LOGE(ATM_DOMAIN, ATM_TAG, "Dlopen libtokensync_sdk failed.");
171 return ERR_LOAD_SO_FAILED;
172 }
173 return tokenSyncKit->GetRemoteHapTokenInfo(deviceID, tokenID);
174 }
175
RegisterTokenSyncCallback(const sptr<IRemoteObject> & callback)176 int32_t TokenModifyNotifier::RegisterTokenSyncCallback(const sptr<IRemoteObject>& callback)
177 {
178 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
179 tokenSyncCallbackObject_ = new TokenSyncCallbackProxy(callback);
180 tokenSyncCallbackDeathRecipient_ = sptr<TokenSyncCallbackDeathRecipient>::MakeSptr();
181 callback->AddDeathRecipient(tokenSyncCallbackDeathRecipient_);
182 LOGI(ATM_DOMAIN, ATM_TAG, "Register token sync callback successful.");
183 return ERR_OK;
184 }
185
UnRegisterTokenSyncCallback()186 int32_t TokenModifyNotifier::UnRegisterTokenSyncCallback()
187 {
188 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
189 if (tokenSyncCallbackObject_ != nullptr && tokenSyncCallbackDeathRecipient_ != nullptr) {
190 tokenSyncCallbackObject_->AsObject()->RemoveDeathRecipient(tokenSyncCallbackDeathRecipient_);
191 }
192 tokenSyncCallbackObject_ = nullptr;
193 tokenSyncCallbackDeathRecipient_ = nullptr;
194 LOGI(ATM_DOMAIN, ATM_TAG, "Unregister token sync callback successful.");
195 return ERR_OK;
196 }
197
198 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
GetCurTaskNum()199 int32_t TokenModifyNotifier::GetCurTaskNum()
200 {
201 return curTaskNum_.load();
202 }
203
AddCurTaskNum()204 void TokenModifyNotifier::AddCurTaskNum()
205 {
206 LOGI(ATM_DOMAIN, ATM_TAG, "Add task!");
207 curTaskNum_++;
208 }
209
ReduceCurTaskNum()210 void TokenModifyNotifier::ReduceCurTaskNum()
211 {
212 LOGI(ATM_DOMAIN, ATM_TAG, "Reduce task!");
213 curTaskNum_--;
214 }
215 #endif
216
NotifyTokenChangedIfNeed()217 void TokenModifyNotifier::NotifyTokenChangedIfNeed()
218 {
219 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
220 if (GetCurTaskNum() > 1) {
221 LOGI(ATM_DOMAIN, ATM_TAG, "Has notify task! taskNum is %{public}d.", GetCurTaskNum());
222 return;
223 }
224
225 std::string taskName = "TokenModify";
226 auto tokenModify = []() {
227 TokenModifyNotifier::GetInstance().NotifyTokenSyncTask();
228 TokenModifyNotifier::GetInstance().ReduceCurTaskNum();
229 };
230 ffrt::submit(tokenModify, {}, {}, ffrt::task_attr().qos(ffrt::qos_default).name(taskName.c_str()));
231 AddCurTaskNum();
232 #else
233 if (notifyTokenWorker_.GetCurTaskNum() > 1) {
234 LOGI(ATM_DOMAIN, ATM_TAG, " has notify task! taskNum is %{public}zu.", notifyTokenWorker_.GetCurTaskNum());
235 return;
236 }
237
238 notifyTokenWorker_.AddTask([]() {
239 TokenModifyNotifier::GetInstance().NotifyTokenSyncTask();
240 });
241 #endif
242 }
243 } // namespace AccessToken
244 } // namespace Security
245 } // namespace OHOS
246