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