• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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