1 /*
2 * Copyright (c) 2021-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 "app_account_subscribe_manager.h"
17 #include <pthread.h>
18 #include <thread>
19 #include "account_log_wrapper.h"
20 #include "app_account_control_manager.h"
21 #include "app_account_data_storage.h"
22 #include "app_account_subscribe_death_recipient.h"
23 #include "iapp_account_event.h"
24 #include "ipc_skeleton.h"
25 #include "ohos_account_kits.h"
26
27 namespace OHOS {
28 namespace AccountSA {
29 namespace {
30 const char THREAD_APP_ACCOUNT_EVENT[] = "appAccountEvent";
31 }
32
AppAccountSubscribeManager()33 AppAccountSubscribeManager::AppAccountSubscribeManager()
34 : subscribeDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
35 new (std::nothrow) AppAccountSubscribeDeathRecipient()))
36 {}
37
GetInstance()38 AppAccountSubscribeManager &AppAccountSubscribeManager::GetInstance()
39 {
40 static AppAccountSubscribeManager *instance = new (std::nothrow) AppAccountSubscribeManager();
41 return *instance;
42 }
43
SubscribeAppAccount(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const sptr<IRemoteObject> & eventListener,const uid_t & uid,const std::string & bundleName,const uint32_t & appIndex)44 ErrCode AppAccountSubscribeManager::SubscribeAppAccount(
45 const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr, const sptr<IRemoteObject> &eventListener,
46 const uid_t &uid, const std::string &bundleName, const uint32_t &appIndex)
47 {
48 if (subscribeInfoPtr == nullptr) {
49 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
50 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
51 }
52
53 if (eventListener == nullptr) {
54 ACCOUNT_LOGE("eventListener is nullptr");
55 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
56 }
57
58 std::vector<std::string> owners;
59 subscribeInfoPtr->GetOwners(owners);
60
61 if (owners.size() == 0) {
62 ACCOUNT_LOGE("owners size is 0");
63 return ERR_APPACCOUNT_SERVICE_OWNERS_SIZE_IS_ZERO;
64 }
65
66 ErrCode result = CheckAppAccess(subscribeInfoPtr, uid, bundleName, appIndex);
67 if (result != ERR_OK) {
68 ACCOUNT_LOGE("failed to check app access, result %{public}d.", result);
69 return result;
70 }
71
72 auto subscribeRecordPtr = std::make_shared<AppAccountSubscribeRecord>();
73 if (subscribeRecordPtr == nullptr) {
74 ACCOUNT_LOGE("subscribeRecordPtr is nullptr");
75 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
76 }
77
78 subscribeRecordPtr->subscribeInfoPtr = subscribeInfoPtr;
79 subscribeRecordPtr->eventListener = eventListener;
80 subscribeRecordPtr->bundleName = bundleName;
81 subscribeRecordPtr->appIndex = appIndex;
82
83 if (subscribeDeathRecipient_ != nullptr) {
84 eventListener->AddDeathRecipient(subscribeDeathRecipient_);
85 }
86
87 return InsertSubscribeRecord(owners, subscribeRecordPtr);
88 }
89
UnsubscribeAppAccount(const sptr<IRemoteObject> & eventListener)90 ErrCode AppAccountSubscribeManager::UnsubscribeAppAccount(const sptr<IRemoteObject> &eventListener)
91 {
92 if (eventListener == nullptr) {
93 ACCOUNT_LOGE("eventListener is nullptr");
94 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
95 }
96
97 if (subscribeDeathRecipient_ != nullptr) {
98 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
99 }
100
101 return RemoveSubscribeRecord(eventListener);
102 }
103
GetSubscribeRecords(const std::string & owner)104 std::vector<AppAccountSubscribeRecordPtr> AppAccountSubscribeManager::GetSubscribeRecords(const std::string &owner)
105 {
106 auto records = std::vector<AppAccountSubscribeRecordPtr>();
107
108 std::lock_guard<std::mutex> lock(mutex_);
109 if (ownerSubscribeRecords_.size() == 0) {
110 return records;
111 }
112
113 auto subscribeRecordsPtr = ownerSubscribeRecords_.find(owner);
114 if (subscribeRecordsPtr == ownerSubscribeRecords_.end()) {
115 return records;
116 }
117
118 auto subscribeRecords = subscribeRecordsPtr->second;
119 for (auto it = subscribeRecords.begin(); it != subscribeRecords.end(); it++) {
120 std::vector<std::string> owners;
121 ErrCode result = (*it)->subscribeInfoPtr->GetOwners(owners);
122 if (result != ERR_OK) {
123 ACCOUNT_LOGE("failed to get owners for subscribeInfoPtr, result %{public}d.", result);
124 return records;
125 }
126
127 if (std::find(owners.begin(), owners.end(), owner) == owners.end()) {
128 ACCOUNT_LOGE("failed to find owner in owners");
129 return records;
130 }
131
132 records.emplace_back(*it);
133 }
134
135 return records;
136 }
137
CheckAppAccess(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const uid_t & uid,const std::string & bundleName,const uint32_t & appIndex)138 ErrCode AppAccountSubscribeManager::CheckAppAccess(const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr,
139 const uid_t &uid, const std::string &bundleName, const uint32_t &appIndex)
140 {
141 if (subscribeInfoPtr == nullptr) {
142 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
143 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
144 }
145
146 std::vector<std::string> owners;
147 subscribeInfoPtr->GetOwners(owners);
148 auto dataStoragePtr = AppAccountControlManager::GetInstance().GetDataStorage(uid);
149 if (dataStoragePtr == nullptr) {
150 ACCOUNT_LOGE("dataStoragePtr is nullptr");
151 return ERR_APPACCOUNT_SERVICE_DATA_STORAGE_PTR_IS_NULLPTR;
152 }
153
154 std::vector<std::string> accessibleAccounts;
155 ErrCode ret = dataStoragePtr->GetAccessibleAccountsFromDataStorage(bundleName, accessibleAccounts);
156 if (ret != ERR_OK) {
157 ACCOUNT_LOGE("failed to get accessible account from data storage, ret %{public}d.", ret);
158 return ret;
159 }
160 for (auto owner : owners) {
161 if (owner == bundleName) {
162 continue;
163 }
164 auto it = std::find_if(
165 accessibleAccounts.begin(),
166 accessibleAccounts.end(),
167 [owner](const std::string &account) {
168 auto position = account.find(owner);
169 if (position != 0) {
170 return false;
171 }
172
173 return true;
174 });
175 if (it == accessibleAccounts.end()) {
176 ACCOUNT_LOGE("failed to find accessible account");
177 return ERR_ACCOUNT_COMMON_PERMISSION_DENIED;
178 }
179 }
180
181 return ERR_OK;
182 }
183
InsertSubscribeRecord(const std::vector<std::string> & owners,const AppAccountSubscribeRecordPtr & subscribeRecordPtr)184 ErrCode AppAccountSubscribeManager::InsertSubscribeRecord(
185 const std::vector<std::string> &owners, const AppAccountSubscribeRecordPtr &subscribeRecordPtr)
186 {
187 if (owners.size() == 0) {
188 ACCOUNT_LOGE("owners size is 0");
189 return ERR_APPACCOUNT_SERVICE_OWNERS_SIZE_IS_ZERO;
190 }
191
192 if (subscribeRecordPtr == nullptr) {
193 ACCOUNT_LOGE("subscribeRecordPtr is nullptr");
194 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
195 }
196
197 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
198
199 for (auto owner : owners) {
200 auto item = ownerSubscribeRecords_.find(owner);
201 if (item != ownerSubscribeRecords_.end()) {
202 item->second.insert(subscribeRecordPtr);
203 } else {
204 std::multiset<AppAccountSubscribeRecordPtr> subscribeRecords;
205 subscribeRecords.insert(subscribeRecordPtr);
206 ownerSubscribeRecords_[owner] = subscribeRecords;
207 }
208 }
209
210 subscribeRecords_.emplace_back(subscribeRecordPtr);
211
212 return ERR_OK;
213 }
214
RemoveSubscribeRecord(const sptr<IRemoteObject> & eventListener)215 ErrCode AppAccountSubscribeManager::RemoveSubscribeRecord(const sptr<IRemoteObject> &eventListener)
216 {
217 if (eventListener == nullptr) {
218 ACCOUNT_LOGE("eventListener is nullptr");
219 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
220 }
221
222 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
223
224 std::vector<std::string> owners;
225 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
226 if (eventListener == (*it)->eventListener) {
227 (*it)->eventListener = nullptr;
228 (*it)->subscribeInfoPtr->GetOwners(owners);
229 subscribeRecords_.erase(it);
230 break;
231 }
232 }
233
234 for (auto owner : owners) {
235 for (auto it = ownerSubscribeRecords_[owner].begin(); it != ownerSubscribeRecords_[owner].end(); ++it) {
236 if ((eventListener == (*it)->eventListener) || ((*it)->eventListener == nullptr)) {
237 (*it)->eventListener = nullptr;
238 ownerSubscribeRecords_[owner].erase(it);
239 break;
240 }
241 }
242
243 if (ownerSubscribeRecords_[owner].size() == 0) {
244 ownerSubscribeRecords_.erase(owner);
245 }
246 }
247
248 return ERR_OK;
249 }
250
PublishAccount(AppAccountInfo & appAccountInfo,const uid_t & uid,const std::string & bundleName)251 bool AppAccountSubscribeManager::PublishAccount(
252 AppAccountInfo &appAccountInfo, const uid_t &uid, const std::string &bundleName)
253 {
254 std::string name;
255 appAccountInfo.GetName(name);
256 uint32_t appIndex = appAccountInfo.GetAppIndex();
257
258 auto eventRecordPtr = std::make_shared<AppAccountEventRecord>();
259 if (eventRecordPtr == nullptr) {
260 ACCOUNT_LOGE("failed to create AppAccountEventRecord");
261 return false;
262 }
263 eventRecordPtr->info = std::make_shared<AppAccountInfo>(appAccountInfo);
264 eventRecordPtr->receivers = GetSubscribeRecords(bundleName);
265 eventRecordPtr->uid = uid;
266 eventRecordPtr->bundleName = bundleName;
267 eventRecordPtr->appIndex = appIndex;
268
269 auto callback = std::bind(&AppAccountSubscribeManager::OnAccountsChanged, this, eventRecordPtr);
270
271 std::thread taskThread(callback);
272 pthread_setname_np(taskThread.native_handle(), THREAD_APP_ACCOUNT_EVENT);
273 taskThread.detach();
274 return true;
275 }
276
OnAccountsChanged(const std::shared_ptr<AppAccountEventRecord> & record)277 ErrCode AppAccountSubscribeManager::OnAccountsChanged(const std::shared_ptr<AppAccountEventRecord> &record)
278 {
279 auto uid = record->uid;
280 auto &controlManagerPtr = AppAccountControlManager::GetInstance();
281 auto dataStoragePtr = controlManagerPtr.GetDataStorage(uid);
282 if (dataStoragePtr == nullptr) {
283 ACCOUNT_LOGE("dataStoragePtr is nullptr");
284 return ERR_APPACCOUNT_SERVICE_DATA_STORAGE_PTR_IS_NULLPTR;
285 }
286
287 for (auto receiver : record->receivers) {
288 std::vector<AppAccountInfo> accessibleAccounts;
289 ErrCode result = controlManagerPtr.GetAllAccessibleAccountsFromDataStorage(
290 accessibleAccounts, receiver->bundleName, dataStoragePtr, record->appIndex);
291 if (result != ERR_OK) {
292 ACCOUNT_LOGE("failed to get all accessible accounts from data storage, result = %{public}d", result);
293 return result;
294 }
295
296 std::vector<AppAccountInfo> appAccounts;
297 result = GetAccessibleAccountsBySubscribeInfo(receiver->subscribeInfoPtr, accessibleAccounts, appAccounts);
298 if (result != ERR_OK) {
299 ACCOUNT_LOGE("failed to get accessible accounts by subscribe info");
300 continue;
301 }
302
303 auto appAccountEventProxy = iface_cast<IAppAccountEvent>(receiver->eventListener);
304 if (appAccountEventProxy == nullptr) {
305 ACCOUNT_LOGE("failed to get app account event proxy");
306 continue;
307 }
308
309 appAccountEventProxy->OnAccountsChanged(appAccounts);
310 }
311
312 return ERR_OK;
313 }
314
GetAccessibleAccountsBySubscribeInfo(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const std::vector<AppAccountInfo> & accessibleAccounts,std::vector<AppAccountInfo> & appAccounts)315 ErrCode AppAccountSubscribeManager::GetAccessibleAccountsBySubscribeInfo(
316 const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr,
317 const std::vector<AppAccountInfo> &accessibleAccounts, std::vector<AppAccountInfo> &appAccounts)
318 {
319 if (subscribeInfoPtr == nullptr) {
320 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
321 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
322 }
323
324 appAccounts.clear();
325
326 std::vector<std::string> owners;
327 subscribeInfoPtr->GetOwners(owners);
328
329 for (auto accessibleAccount : accessibleAccounts) {
330 std::string name;
331 accessibleAccount.GetName(name);
332
333 std::string owner;
334 accessibleAccount.GetOwner(owner);
335
336 if (std::find(owners.begin(), owners.end(), owner) != owners.end()) {
337 appAccounts.emplace_back(accessibleAccount);
338 }
339 }
340
341 return ERR_OK;
342 }
343 } // namespace AccountSA
344 } // namespace OHOS
345