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