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_constants.h"
20 #include "account_log_wrapper.h"
21 #include "app_account_control_manager.h"
22 #include "app_account_data_storage.h"
23 #include "app_account_subscribe_death_recipient.h"
24 #include "iapp_account_event.h"
25 #include "ipc_skeleton.h"
26 #include "ohos_account_kits.h"
27
28 namespace OHOS {
29 namespace AccountSA {
30 namespace {
31 const char THREAD_APP_ACCOUNT_EVENT[] = "appAccountEvent";
32 const std::string HYPHEN = "#";
33 }
34
AppAccountSubscribeManager()35 AppAccountSubscribeManager::AppAccountSubscribeManager()
36 : subscribeDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
37 new (std::nothrow) AppAccountSubscribeDeathRecipient()))
38 {}
39
GetInstance()40 AppAccountSubscribeManager &AppAccountSubscribeManager::GetInstance()
41 {
42 static AppAccountSubscribeManager *instance = new (std::nothrow) AppAccountSubscribeManager();
43 return *instance;
44 }
45
SubscribeAppAccount(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const sptr<IRemoteObject> & eventListener,const uid_t & uid,const std::string & bundleName,const uint32_t & appIndex)46 ErrCode AppAccountSubscribeManager::SubscribeAppAccount(
47 const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr, const sptr<IRemoteObject> &eventListener,
48 const uid_t &uid, const std::string &bundleName, const uint32_t &appIndex)
49 {
50 if (subscribeInfoPtr == nullptr) {
51 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
52 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
53 }
54
55 if (eventListener == nullptr) {
56 ACCOUNT_LOGE("eventListener is nullptr");
57 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
58 }
59
60 std::vector<std::string> owners;
61 subscribeInfoPtr->GetOwners(owners);
62
63 if (owners.size() == 0) {
64 ACCOUNT_LOGE("owners size is 0");
65 return ERR_APPACCOUNT_SERVICE_OWNERS_SIZE_IS_ZERO;
66 }
67
68 ErrCode result = CheckAppAccess(subscribeInfoPtr, uid, bundleName, appIndex);
69 if (result != ERR_OK) {
70 ACCOUNT_LOGE("failed to check app access, result %{public}d.", result);
71 return result;
72 }
73
74 auto subscribeRecordPtr = std::make_shared<AppAccountSubscribeRecord>();
75 if (subscribeRecordPtr == nullptr) {
76 ACCOUNT_LOGE("subscribeRecordPtr is nullptr");
77 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
78 }
79
80 subscribeRecordPtr->subscribeInfoPtr = subscribeInfoPtr;
81 subscribeRecordPtr->eventListener = eventListener;
82 subscribeRecordPtr->bundleName = bundleName;
83 subscribeRecordPtr->appIndex = appIndex;
84 subscribeRecordPtr->subscribedAppIndex = 0;
85
86 if (subscribeDeathRecipient_ != nullptr) {
87 eventListener->AddDeathRecipient(subscribeDeathRecipient_);
88 }
89
90 return InsertSubscribeRecord(owners, subscribeRecordPtr);
91 }
92
UnsubscribeAppAccount(const sptr<IRemoteObject> & eventListener,std::vector<std::string> & owners)93 ErrCode AppAccountSubscribeManager::UnsubscribeAppAccount(const sptr<IRemoteObject> &eventListener,
94 std::vector<std::string> &owners)
95 {
96 if (eventListener == nullptr) {
97 ACCOUNT_LOGE("eventListener is nullptr");
98 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
99 }
100
101 if (subscribeDeathRecipient_ != nullptr) {
102 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
103 }
104
105 return RemoveSubscribeRecord(eventListener, owners);
106 }
107
GetSubscribeRecords(const std::string & owner,const uint32_t & appIndex)108 std::vector<AppAccountSubscribeRecordPtr> AppAccountSubscribeManager::GetSubscribeRecords(const std::string &owner,
109 const uint32_t &appIndex)
110 {
111 auto records = std::vector<AppAccountSubscribeRecordPtr>();
112
113 std::lock_guard<std::mutex> lock(mutex_);
114 if (ownerSubscribeRecords_.size() == 0) {
115 return records;
116 }
117
118 auto subscribeRecordsPtr = ownerSubscribeRecords_.find(owner);
119 if (subscribeRecordsPtr == ownerSubscribeRecords_.end()) {
120 return records;
121 }
122
123 auto subscribeRecords = subscribeRecordsPtr->second;
124 for (auto it = subscribeRecords.begin(); it != subscribeRecords.end(); it++) {
125 std::vector<std::string> owners;
126 ErrCode result = (*it)->subscribeInfoPtr->GetOwners(owners);
127 if (result != ERR_OK) {
128 ACCOUNT_LOGE("failed to get owners for subscribeInfoPtr, result %{public}d.", result);
129 return records;
130 }
131
132 if (std::find(owners.begin(), owners.end(), owner) == owners.end()) {
133 ACCOUNT_LOGE("failed to find owner in owners");
134 return records;
135 }
136
137 if (appIndex != (*it)->subscribedAppIndex) {
138 continue;
139 }
140
141 records.emplace_back(*it);
142 }
143
144 return records;
145 }
146
CheckAppIsMaster(const std::string & account)147 bool AppAccountSubscribeManager::CheckAppIsMaster(const std::string &account)
148 {
149 size_t firstHashPos = account.find('#');
150 if (firstHashPos == std::string::npos) {
151 return false;
152 }
153 size_t secondHashPos = account.find('#', firstHashPos + 1);
154 if (secondHashPos == std::string::npos) {
155 return false;
156 }
157 std::string indexStr = account.substr(firstHashPos + 1, secondHashPos - firstHashPos - 1);
158 int index = -1;
159 if (!StrToInt(indexStr, index)) {
160 return false;
161 }
162 return (index == 0);
163 }
164
CheckAppAccess(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const uid_t & uid,const std::string & bundleName,const uint32_t & appIndex)165 ErrCode AppAccountSubscribeManager::CheckAppAccess(const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr,
166 const uid_t &uid, const std::string &bundleName, const uint32_t &appIndex)
167 {
168 if (subscribeInfoPtr == nullptr) {
169 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
170 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
171 }
172
173 std::vector<std::string> owners;
174 subscribeInfoPtr->GetOwners(owners);
175 auto dataStoragePtr = AppAccountControlManager::GetInstance().GetDataStorage(uid);
176 if (dataStoragePtr == nullptr) {
177 ACCOUNT_LOGE("dataStoragePtr is nullptr");
178 return ERR_APPACCOUNT_SERVICE_DATA_STORAGE_PTR_IS_NULLPTR;
179 }
180
181 std::vector<std::string> accessibleAccounts;
182 std::string bundleKey = bundleName + (appIndex == 0 ? "" : HYPHEN + std::to_string(appIndex));
183 ErrCode ret = dataStoragePtr->GetAccessibleAccountsFromDataStorage(bundleKey, accessibleAccounts);
184 if (ret != ERR_OK) {
185 ACCOUNT_LOGE("failed to get accessible account from data storage, ret %{public}d.", ret);
186 return ret;
187 }
188 for (auto it = accessibleAccounts.begin(); it != accessibleAccounts.end();) {
189 if (!CheckAppIsMaster(*it)) {
190 it = accessibleAccounts.erase(it);
191 } else {
192 it++;
193 }
194 }
195 for (auto owner : owners) {
196 if (owner == bundleKey) {
197 continue;
198 }
199 auto it = std::find_if(
200 accessibleAccounts.begin(),
201 accessibleAccounts.end(),
202 [owner](const std::string &account) {
203 auto position = account.find(owner);
204 if (position != 0) {
205 return false;
206 }
207
208 return true;
209 });
210 if (it == accessibleAccounts.end()) {
211 ACCOUNT_LOGE("failed to find accessible account");
212 return ERR_ACCOUNT_COMMON_PERMISSION_DENIED;
213 }
214 }
215
216 return ERR_OK;
217 }
218
ClearOldData(const sptr<IRemoteObject> & eventListener,const std::string & owner,std::map<std::string,std::multiset<AppAccountSubscribeRecordPtr>>::iterator & item)219 void AppAccountSubscribeManager::ClearOldData(const sptr<IRemoteObject> &eventListener, const std::string &owner,
220 std::map<std::string, std::multiset<AppAccountSubscribeRecordPtr>>::iterator &item)
221 {
222 for (auto it = item->second.begin(); it != item->second.end(); ++it) {
223 if ((eventListener == (*it)->eventListener) || ((*it)->eventListener == nullptr)) {
224 ACCOUNT_LOGI("The subscription record already exists. Update the owner operation");
225 (*it)->eventListener = nullptr;
226 ownerSubscribeRecords_[owner].erase(it);
227 break;
228 }
229 }
230 }
231
InsertSubscribeRecord(const std::vector<std::string> & owners,const AppAccountSubscribeRecordPtr & subscribeRecordPtr)232 ErrCode AppAccountSubscribeManager::InsertSubscribeRecord(
233 const std::vector<std::string> &owners, const AppAccountSubscribeRecordPtr &subscribeRecordPtr)
234 {
235 if (owners.size() == 0) {
236 ACCOUNT_LOGE("owners size is 0");
237 return ERR_APPACCOUNT_SERVICE_OWNERS_SIZE_IS_ZERO;
238 }
239
240 if (subscribeRecordPtr == nullptr) {
241 ACCOUNT_LOGE("subscribeRecordPtr is nullptr");
242 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
243 }
244
245 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
246
247 auto eventListener = subscribeRecordPtr->eventListener;
248 for (auto owner : owners) {
249 auto item = ownerSubscribeRecords_.find(owner);
250 if (item != ownerSubscribeRecords_.end()) {
251 ClearOldData(eventListener, owner, item);
252 item->second.insert(subscribeRecordPtr);
253 } else {
254 std::multiset<AppAccountSubscribeRecordPtr> subscribeRecords;
255 subscribeRecords.insert(subscribeRecordPtr);
256 ownerSubscribeRecords_[owner] = subscribeRecords;
257 }
258 }
259 ACCOUNT_LOGI("Update owner only, owner size=%{public}zu.", owners.size());
260
261 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
262 if ((eventListener == (*it)->eventListener) || ((*it)->eventListener == nullptr)) {
263 (*it)->eventListener = nullptr;
264 subscribeRecords_.erase(it);
265 break;
266 }
267 }
268 subscribeRecords_.emplace_back(subscribeRecordPtr);
269
270 return ERR_OK;
271 }
272
RefreshOldData(const sptr<IRemoteObject> & eventListener,const std::string & owner,const std::vector<std::string> & ownerList,const std::vector<std::string> & newOwners)273 void AppAccountSubscribeManager::RefreshOldData(const sptr<IRemoteObject> &eventListener, const std::string &owner,
274 const std::vector<std::string> &ownerList, const std::vector<std::string> &newOwners)
275 {
276 for (auto it = ownerSubscribeRecords_[owner].begin(); it != ownerSubscribeRecords_[owner].end(); ++it) {
277 if ((eventListener == (*it)->eventListener) || ((*it)->eventListener == nullptr)) {
278 ACCOUNT_LOGI("Clear owner only, owner size=%{public}zu.", newOwners.size());
279 if ((!ownerList.empty()) && (std::find(ownerList.begin(), ownerList.end(), owner) == ownerList.end())) {
280 (*it)->subscribeInfoPtr->SetOwners(newOwners);
281 break;
282 }
283 (*it)->eventListener = nullptr;
284 ownerSubscribeRecords_[owner].erase(it);
285 break;
286 }
287 }
288 }
289
RemoveSubscribeRecord(const sptr<IRemoteObject> & eventListener,std::vector<std::string> & ownerList)290 ErrCode AppAccountSubscribeManager::RemoveSubscribeRecord(const sptr<IRemoteObject> &eventListener,
291 std::vector<std::string> &ownerList)
292 {
293 if (eventListener == nullptr) {
294 ACCOUNT_LOGE("eventListener is nullptr");
295 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
296 }
297
298 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
299
300 std::vector<std::string> owners;
301 std::vector<std::string> newOwners;
302 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
303 if (eventListener == (*it)->eventListener) {
304 (*it)->subscribeInfoPtr->GetOwners(owners);
305 if (!ownerList.empty()) {
306 std::sort(owners.begin(), owners.end());
307 std::sort(ownerList.begin(), ownerList.end());
308 std::set_difference(owners.begin(), owners.end(), ownerList.begin(), ownerList.end(),
309 std::back_inserter(newOwners));
310 (*it)->subscribeInfoPtr->SetOwners(newOwners);
311 break;
312 }
313 subscribeRecords_.erase(it);
314 break;
315 }
316 }
317
318 for (auto owner : owners) {
319 RefreshOldData(eventListener, owner, ownerList, newOwners);
320
321 if (ownerSubscribeRecords_[owner].size() == 0) {
322 ownerSubscribeRecords_.erase(owner);
323 }
324 }
325
326 return ERR_OK;
327 }
328
PublishAccount(AppAccountInfo & appAccountInfo,const uid_t & uid,const std::string & bundleName)329 bool AppAccountSubscribeManager::PublishAccount(
330 AppAccountInfo &appAccountInfo, const uid_t &uid, const std::string &bundleName)
331 {
332 std::string name;
333 appAccountInfo.GetName(name);
334 uint32_t appIndex = appAccountInfo.GetAppIndex();
335
336 auto eventRecordPtr = std::make_shared<AppAccountEventRecord>();
337 if (eventRecordPtr == nullptr) {
338 ACCOUNT_LOGE("failed to create AppAccountEventRecord");
339 return false;
340 }
341 eventRecordPtr->info = std::make_shared<AppAccountInfo>(appAccountInfo);
342 eventRecordPtr->receivers = GetSubscribeRecords(bundleName, appIndex);
343 eventRecordPtr->uid = uid;
344 eventRecordPtr->bundleName = bundleName;
345 eventRecordPtr->appIndex = appIndex;
346
347 auto callback = [this, eventRecordPtr] { this->OnAccountsChanged(eventRecordPtr); };
348
349 std::thread taskThread(callback);
350 pthread_setname_np(taskThread.native_handle(), THREAD_APP_ACCOUNT_EVENT);
351 taskThread.detach();
352 return true;
353 }
354
OnAccountsChanged(const std::shared_ptr<AppAccountEventRecord> & record)355 ErrCode AppAccountSubscribeManager::OnAccountsChanged(const std::shared_ptr<AppAccountEventRecord> &record)
356 {
357 auto uid = record->uid;
358 auto &controlManagerPtr = AppAccountControlManager::GetInstance();
359 auto dataStoragePtr = controlManagerPtr.GetDataStorage(uid);
360 if (dataStoragePtr == nullptr) {
361 ACCOUNT_LOGE("dataStoragePtr is nullptr");
362 return ERR_APPACCOUNT_SERVICE_DATA_STORAGE_PTR_IS_NULLPTR;
363 }
364
365 for (auto receiver : record->receivers) {
366 bool isAuthorizedApp = false;
367 record->info->CheckAppAccess(receiver->bundleName, isAuthorizedApp);
368 if (!isAuthorizedApp && receiver->bundleName != record->info->GetOwner()) {
369 continue;
370 }
371 std::vector<AppAccountInfo> accessibleAccounts;
372 ErrCode result = controlManagerPtr.GetAllAccessibleAccountsFromDataStorage(
373 accessibleAccounts, receiver->bundleName, dataStoragePtr, receiver->appIndex);
374 if (result != ERR_OK) {
375 ACCOUNT_LOGE("failed to get all accessible accounts from data storage, result = %{public}d", result);
376 return result;
377 }
378
379 std::vector<AppAccountInfo> appAccounts;
380 result = GetAccessibleAccountsBySubscribeInfo(receiver->subscribeInfoPtr, accessibleAccounts, appAccounts);
381 if (result != ERR_OK) {
382 ACCOUNT_LOGE("failed to get accessible accounts by subscribe info");
383 continue;
384 }
385
386 auto appAccountEventProxy = iface_cast<IAppAccountEvent>(receiver->eventListener);
387 if (appAccountEventProxy == nullptr) {
388 ACCOUNT_LOGE("failed to get app account event proxy");
389 continue;
390 }
391
392 int32_t retryTimes = 0;
393 ErrCode errCode;
394 while (retryTimes < Constants::MAX_RETRY_TIMES) {
395 errCode = appAccountEventProxy->OnAccountsChanged(appAccounts, record->info->GetOwner());
396 if (errCode == ERR_OK || (errCode != Constants::E_IPC_ERROR &&
397 errCode != Constants::E_IPC_SA_DIED)) {
398 break;
399 }
400 retryTimes++;
401 ACCOUNT_LOGE("Failed to SendRequest, code = %{public}d, retryTimes = %{public}d",
402 errCode, retryTimes);
403 std::this_thread::sleep_for(std::chrono::milliseconds(Constants::DELAY_FOR_EXCEPTION));
404 }
405 }
406
407 return ERR_OK;
408 }
409
GetAccessibleAccountsBySubscribeInfo(const std::shared_ptr<AppAccountSubscribeInfo> & subscribeInfoPtr,const std::vector<AppAccountInfo> & accessibleAccounts,std::vector<AppAccountInfo> & appAccounts)410 ErrCode AppAccountSubscribeManager::GetAccessibleAccountsBySubscribeInfo(
411 const std::shared_ptr<AppAccountSubscribeInfo> &subscribeInfoPtr,
412 const std::vector<AppAccountInfo> &accessibleAccounts, std::vector<AppAccountInfo> &appAccounts)
413 {
414 if (subscribeInfoPtr == nullptr) {
415 ACCOUNT_LOGE("subscribeInfoPtr is nullptr");
416 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
417 }
418
419 appAccounts.clear();
420
421 std::vector<std::string> owners;
422 subscribeInfoPtr->GetOwners(owners);
423
424 for (auto accessibleAccount : accessibleAccounts) {
425 std::string name;
426 accessibleAccount.GetName(name);
427
428 std::string owner;
429 accessibleAccount.GetOwner(owner);
430
431 if (std::find(owners.begin(), owners.end(), owner) != owners.end()) {
432 appAccounts.emplace_back(accessibleAccount);
433 }
434 }
435
436 return ERR_OK;
437 }
438 } // namespace AccountSA
439 } // namespace OHOS
440