1 /*
2 * Copyright (c) 2022 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_id_manager.h"
19 #include "accesstoken_info_manager.h"
20 #include "accesstoken_log.h"
21 #include "access_token_error.h"
22 #include "hap_token_info.h"
23 #include "hap_token_info_inner.h"
24 #include "token_sync_kit.h"
25
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 namespace {
30 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "TokenModifyNotifier"};
31 }
32
33 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
TokenModifyNotifier()34 TokenModifyNotifier::TokenModifyNotifier() : hasInited_(false), curTaskNum_(0) {}
35 #else
TokenModifyNotifier()36 TokenModifyNotifier::TokenModifyNotifier() : hasInited_(false), notifyTokenWorker_("TokenModify") {}
37 #endif
38
~TokenModifyNotifier()39 TokenModifyNotifier::~TokenModifyNotifier()
40 {
41 if (!hasInited_) {
42 return;
43 }
44 #ifndef RESOURCESCHEDULE_FFRT_ENABLE
45 this->notifyTokenWorker_.Stop();
46 #endif
47 this->hasInited_ = false;
48 }
49
AddHapTokenObservation(AccessTokenID tokenID)50 void TokenModifyNotifier::AddHapTokenObservation(AccessTokenID tokenID)
51 {
52 if (AccessTokenIDManager::GetInstance().GetTokenIdType(tokenID) != TOKEN_HAP) {
53 ACCESSTOKEN_LOG_INFO(LABEL, "Observation token is not hap token");
54 return;
55 }
56 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
57 if (observationSet_.count(tokenID) <= 0) {
58 observationSet_.insert(tokenID);
59 }
60 }
61
NotifyTokenDelete(AccessTokenID tokenID)62 void TokenModifyNotifier::NotifyTokenDelete(AccessTokenID tokenID)
63 {
64 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
65 if (observationSet_.count(tokenID) <= 0) {
66 ACCESSTOKEN_LOG_DEBUG(LABEL, "hap token is not observed");
67 return;
68 }
69 observationSet_.erase(tokenID);
70 deleteTokenList_.emplace_back(tokenID);
71 NotifyTokenChangedIfNeed();
72 }
73
NotifyTokenModify(AccessTokenID tokenID)74 void TokenModifyNotifier::NotifyTokenModify(AccessTokenID tokenID)
75 {
76 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
77 if (observationSet_.count(tokenID) <= 0) {
78 ACCESSTOKEN_LOG_DEBUG(LABEL, "hap token is not observed");
79 return;
80 }
81 modifiedTokenList_.emplace_back(tokenID);
82 NotifyTokenChangedIfNeed();
83 }
84
GetInstance()85 TokenModifyNotifier& TokenModifyNotifier::GetInstance()
86 {
87 static TokenModifyNotifier instance;
88
89 if (!instance.hasInited_) {
90 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(instance.initLock_);
91 if (!instance.hasInited_) {
92 #ifndef RESOURCESCHEDULE_FFRT_ENABLE
93 instance.notifyTokenWorker_.Start(1);
94 #endif
95 instance.hasInited_ = true;
96 }
97 }
98
99 return instance;
100 }
101
NotifyTokenSyncTask()102 void TokenModifyNotifier::NotifyTokenSyncTask()
103 {
104 ACCESSTOKEN_LOG_INFO(LABEL, "called!");
105
106 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->Notifylock_);
107 for (AccessTokenID deleteToken : deleteTokenList_) {
108 TokenSyncKit::DeleteRemoteHapTokenInfo(deleteToken);
109 }
110
111 for (AccessTokenID modifyToken : modifiedTokenList_) {
112 HapTokenInfoForSync hapSync;
113 int ret = AccessTokenInfoManager::GetInstance().GetHapTokenSync(modifyToken, hapSync);
114 if (ret != RET_SUCCESS) {
115 ACCESSTOKEN_LOG_ERROR(LABEL, "the hap token 0x%{public}x need to sync is not found!", modifyToken);
116 continue;
117 }
118 TokenSyncKit::UpdateRemoteHapTokenInfo(hapSync);
119 }
120 deleteTokenList_.clear();
121 modifiedTokenList_.clear();
122
123 ACCESSTOKEN_LOG_INFO(LABEL, "over!");
124 }
125
126 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
GetCurTaskNum()127 int32_t TokenModifyNotifier::GetCurTaskNum()
128 {
129 return curTaskNum_.load();
130 }
131
AddCurTaskNum()132 void TokenModifyNotifier::AddCurTaskNum()
133 {
134 ACCESSTOKEN_LOG_INFO(LABEL, "Add task!");
135 curTaskNum_++;
136 }
137
ReduceCurTaskNum()138 void TokenModifyNotifier::ReduceCurTaskNum()
139 {
140 ACCESSTOKEN_LOG_INFO(LABEL, "Reduce task!");
141 curTaskNum_--;
142 }
143 #endif
144
NotifyTokenChangedIfNeed()145 void TokenModifyNotifier::NotifyTokenChangedIfNeed()
146 {
147 #ifdef RESOURCESCHEDULE_FFRT_ENABLE
148 if (GetCurTaskNum() > 1) {
149 ACCESSTOKEN_LOG_INFO(LABEL, "has notify task! taskNum is %{public}d.", GetCurTaskNum());
150 return;
151 }
152
153 std::string taskName = "TokenModify";
154 auto tokenModify = []() {
155 TokenModifyNotifier::GetInstance().NotifyTokenSyncTask();
156 TokenModifyNotifier::GetInstance().ReduceCurTaskNum();
157 };
158 ffrt::submit(tokenModify, {}, {}, ffrt::task_attr().qos(ffrt::qos_default).name(taskName.c_str()));
159 AddCurTaskNum();
160 #else
161 if (notifyTokenWorker_.GetCurTaskNum() > 1) {
162 ACCESSTOKEN_LOG_INFO(LABEL, " has notify task! taskNum is %{public}zu.", notifyTokenWorker_.GetCurTaskNum());
163 return;
164 }
165
166 notifyTokenWorker_.AddTask([]() {
167 TokenModifyNotifier::GetInstance().NotifyTokenSyncTask();
168 });
169 #endif
170 }
171 } // namespace AccessToken
172 } // namespace Security
173 } // namespace OHOS
174