1 /*
2 * Copyright (c) 2022-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 "active_status_callback_manager.h"
17
18 #include <future>
19 #include <thread>
20 #include <datetime_ex.h>
21 #include <pthread.h>
22
23 #include "accesstoken_dfx_define.h"
24 #include "accesstoken_log.h"
25 #include "privacy_error.h"
26
27 namespace OHOS {
28 namespace Security {
29 namespace AccessToken {
30 namespace {
31 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
32 LOG_CORE, SECURITY_DOMAIN_PRIVACY, "ActiveStatusCallbackManager"
33 };
34 static const uint32_t MAX_CALLBACK_SIZE = 1024;
35 std::recursive_mutex g_instanceMutex;
36 }
37
GetInstance()38 ActiveStatusCallbackManager& ActiveStatusCallbackManager::GetInstance()
39 {
40 static ActiveStatusCallbackManager* instance = nullptr;
41 if (instance == nullptr) {
42 std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
43 if (instance == nullptr) {
44 instance = new ActiveStatusCallbackManager();
45 }
46 }
47 return *instance;
48 }
49
ActiveStatusCallbackManager()50 ActiveStatusCallbackManager::ActiveStatusCallbackManager()
51 : callbackDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
52 new (std::nothrow) PermActiveStatusCallbackDeathRecipient()))
53 {
54 }
55
~ActiveStatusCallbackManager()56 ActiveStatusCallbackManager::~ActiveStatusCallbackManager()
57 {
58 }
59
60 #ifdef EVENTHANDLER_ENABLE
InitEventHandler(const std::shared_ptr<AccessEventHandler> & eventHandler)61 void ActiveStatusCallbackManager::InitEventHandler(const std::shared_ptr<AccessEventHandler>& eventHandler)
62 {
63 eventHandler_ = eventHandler;
64 }
65 #endif
66
AddCallback(AccessTokenID regiterTokenId,const std::vector<std::string> & permList,const sptr<IRemoteObject> & callback)67 int32_t ActiveStatusCallbackManager::AddCallback(
68 AccessTokenID regiterTokenId, const std::vector<std::string>& permList, const sptr<IRemoteObject>& callback)
69 {
70 if (callback == nullptr) {
71 ACCESSTOKEN_LOG_ERROR(LABEL, "Input is nullptr");
72 return PrivacyError::ERR_PARAM_INVALID;
73 }
74
75 std::lock_guard<std::mutex> lock(mutex_);
76 if (callbackDataList_.size() >= MAX_CALLBACK_SIZE) {
77 ACCESSTOKEN_LOG_ERROR(LABEL, "List size has reached max value");
78 return PrivacyError::ERR_CALLBACKS_EXCEED_LIMITATION;
79 }
80 callback->AddDeathRecipient(callbackDeathRecipient_);
81
82 CallbackData recordInstance;
83 recordInstance.registerTokenId = regiterTokenId;
84 recordInstance.callbackObject_ = callback;
85 recordInstance.permList_ = permList;
86
87 callbackDataList_.emplace_back(recordInstance);
88
89 ACCESSTOKEN_LOG_INFO(LABEL, "RecordInstance is added");
90 return RET_SUCCESS;
91 }
92
RemoveCallback(const sptr<IRemoteObject> & callback)93 int32_t ActiveStatusCallbackManager::RemoveCallback(const sptr<IRemoteObject>& callback)
94 {
95 ACCESSTOKEN_LOG_INFO(LABEL, "Called");
96 if (callback == nullptr) {
97 ACCESSTOKEN_LOG_ERROR(LABEL, "Callback is nullptr.");
98 return PrivacyError::ERR_PARAM_INVALID;
99 }
100
101 std::lock_guard<std::mutex> lock(mutex_);
102
103 for (auto it = callbackDataList_.begin(); it != callbackDataList_.end(); ++it) {
104 if (callback == (*it).callbackObject_) {
105 ACCESSTOKEN_LOG_INFO(LABEL, "Find callback");
106 if (callbackDeathRecipient_ != nullptr) {
107 callback->RemoveDeathRecipient(callbackDeathRecipient_);
108 }
109 (*it).callbackObject_ = nullptr;
110 callbackDataList_.erase(it);
111 break;
112 }
113 }
114 return RET_SUCCESS;
115 }
116
NeedCalled(const std::vector<std::string> & permList,const std::string & permName)117 bool ActiveStatusCallbackManager::NeedCalled(const std::vector<std::string>& permList, const std::string& permName)
118 {
119 if (permList.empty()) {
120 return true;
121 }
122 return std::any_of(permList.begin(), permList.end(),
123 [permName](const std::string& perm) { return perm == permName; });
124 }
125
126
ActiveStatusChange(AccessTokenID tokenId,const std::string & permName,const std::string & deviceId,ActiveChangeType changeType)127 void ActiveStatusCallbackManager::ActiveStatusChange(
128 AccessTokenID tokenId, const std::string& permName, const std::string& deviceId, ActiveChangeType changeType)
129 {
130 std::vector<sptr<IRemoteObject>> list;
131 {
132 std::lock_guard<std::mutex> lock(mutex_);
133 for (auto it = callbackDataList_.begin(); it != callbackDataList_.end(); ++it) {
134 std::vector<std::string> permList = (*it).permList_;
135 if (!NeedCalled(permList, permName)) {
136 ACCESSTOKEN_LOG_INFO(LABEL, "TokenId %{public}u, perm %{public}s", tokenId, permName.c_str());
137 continue;
138 }
139 list.emplace_back((*it).callbackObject_);
140 }
141 }
142 for (auto it = list.begin(); it != list.end(); ++it) {
143 sptr<IPermActiveStatusCallback> callback = new PermActiveStatusChangeCallbackProxy(*it);
144 if (callback != nullptr) {
145 ActiveChangeResponse resInfo;
146 resInfo.type = changeType;
147 resInfo.permissionName = permName;
148 resInfo.tokenID = tokenId;
149 resInfo.deviceId = deviceId;
150 ACCESSTOKEN_LOG_INFO(LABEL,
151 "callback execute tokenId %{public}u, permision %{public}s changeType %{public}d",
152 tokenId, permName.c_str(), changeType);
153 callback->ActiveStatusChangeCallback(resInfo);
154 }
155 }
156 }
157
ExecuteCallbackAsync(AccessTokenID tokenId,const std::string & permName,const std::string & deviceId,ActiveChangeType changeType)158 void ActiveStatusCallbackManager::ExecuteCallbackAsync(
159 AccessTokenID tokenId, const std::string& permName, const std::string& deviceId, ActiveChangeType changeType)
160 {
161 if (changeType == PERM_ACTIVE_IN_BACKGROUND) {
162 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "PERMISSION_CHECK_EVENT",
163 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "CODE", BACKGROUND_CALL_EVENT,
164 "CALLER_TOKENID", tokenId, "PERMISSION_NAME", permName, "REASON", "background call");
165 }
166
167 #ifdef EVENTHANDLER_ENABLE
168 if (eventHandler_ == nullptr) {
169 ACCESSTOKEN_LOG_ERROR(LABEL, "Fail to get EventHandler");
170 return;
171 }
172 std::string taskName = permName + std::to_string(tokenId);
173 ACCESSTOKEN_LOG_INFO(LABEL, "Add permission task name:%{public}s", taskName.c_str());
174 std::function<void()> task = ([tokenId, permName, deviceId, changeType]() {
175 ActiveStatusCallbackManager::GetInstance().ActiveStatusChange(tokenId, permName, deviceId, changeType);
176 ACCESSTOKEN_LOG_INFO(LABEL,
177 "Token: %{public}u, permName: %{public}s, changeType: %{public}d, ActiveStatusChange end",
178 tokenId, permName.c_str(), changeType);
179 });
180 eventHandler_->ProxyPostTask(task, taskName);
181 ACCESSTOKEN_LOG_INFO(LABEL, "The callback execution is complete");
182 return;
183 #else
184 ACCESSTOKEN_LOG_INFO(LABEL, "Event handler is unenabled");
185 return;
186 #endif
187 }
188 } // namespace AccessToken
189 } // namespace Security
190 } // namespace OHOS
191