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