• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 "distributed_ability_manager_service.h"
17 
18 #include <chrono>
19 #include <thread>
20 
21 #include "ability_manager_client.h"
22 #include "accesstoken_kit.h"
23 #include "base/continuationmgr_log.h"
24 #include "base/parcel_helper.h"
25 #include "bundlemgr/bundle_mgr_interface.h"
26 #include "bundlemgr/bundle_mgr_proxy.h"
27 #include "continuation_manager/app_connection_stub.h"
28 #include "continuation_manager/app_device_callback_stub.h"
29 #include "continuation_manager/device_selection_notifier_proxy.h"
30 #include "continuation_manager/notifier_death_recipient.h"
31 #include "distributed_ability_manager_dumper.h"
32 #include "file_ex.h"
33 #include "ipc_skeleton.h"
34 #include "iservice_registry.h"
35 #include "os_account_manager.h"
36 #include "parameters.h"
37 #include "system_ability_definition.h"
38 
39 namespace OHOS {
40 namespace DistributedSchedule {
41 namespace {
42 const std::string TAG = "ContinuationManagerService";
43 const std::u16string HIPLAY_PANEL_INTERFACE_TOKEN = u"ohos.hiplay.panel";
44 const std::string TOKEN_KEY = "distributedsched.continuationmanager.token";
45 const std::string DEFAULT_TOKEN_VALUE = "0";
46 const std::string DMS_HIPLAY_ACTION = "ohos.ability.action.deviceSelect";
47 const std::string PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC";
48 constexpr int32_t MAX_TOKEN_NUM = 100000000;
49 constexpr int32_t MAX_REGISTER_NUM = 600;
50 constexpr int32_t START_DEVICE_MANAGER_CODE = 1;
51 constexpr int32_t UPDATE_CONNECT_STATUS_CODE = 2;
52 constexpr int32_t VALUE_NULL = -1; // no object in parcel
53 constexpr int32_t VALUE_OBJECT = 1; // object exist in parcel
54 }
55 
56 IMPLEMENT_SINGLE_INSTANCE(DistributedAbilityManagerService);
57 const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&DistributedAbilityManagerService::GetInstance());
58 
DistributedAbilityManagerService()59 DistributedAbilityManagerService::DistributedAbilityManagerService() : SystemAbility(CONTINUATION_MANAGER_SA_ID, true)
60 {
61 }
62 
OnStart()63 void DistributedAbilityManagerService::OnStart()
64 {
65     HILOGI("begin");
66     {
67         std::lock_guard<std::mutex> tokenLock(tokenMutex_);
68         std::string tokenStr = system::GetParameter(TOKEN_KEY, DEFAULT_TOKEN_VALUE);
69         if (!tokenStr.empty()) {
70             token_.store(std::atoi(tokenStr.c_str()));
71         }
72     }
73     notifierDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new NotifierDeathRecipient());
74     if (continuationHandler_ == nullptr) {
75         continuationHandler_ = std::make_shared<ffrt::queue>("ContinuationMgr");
76     }
77     Publish(this);
78 }
79 
OnStop()80 void DistributedAbilityManagerService::OnStop()
81 {
82     HILOGI("begin");
83 }
84 
Dump(int32_t fd,const std::vector<std::u16string> & args)85 int32_t DistributedAbilityManagerService::Dump(int32_t fd, const std::vector<std::u16string>& args)
86 {
87     std::vector<std::string> argsInStr8;
88     for (const auto& arg : args) {
89         argsInStr8.emplace_back(Str16ToStr8(arg));
90     }
91     std::string result;
92     DistributedAbilityManagerDumper::Dump(argsInStr8, result);
93     if (!SaveStringToFd(fd, result)) {
94         HILOGE("save to fd failed");
95         return DMS_WRITE_FILE_FAILED_ERR;
96     }
97     return ERR_OK;
98 }
99 
DumpAppRegisterInfo(std::string & info)100 void DistributedAbilityManagerService::DumpAppRegisterInfo(std::string& info)
101 {
102     std::lock_guard<std::mutex> autoLock(tokenMapMutex_);
103     info += "application register infos:\n";
104     info += "  ";
105     if (!tokenMap_.empty()) {
106         for (const auto& tokenMap : tokenMap_) {
107             info += "accessToken: ";
108             info += std::to_string(tokenMap.first);
109             std::vector<int32_t> tokenVec = tokenMap.second;
110             DumpNotifierLocked(tokenVec, info);
111             info += "\n";
112             info += "  ";
113         }
114     } else {
115         info += "  <none info>\n";
116     }
117 }
118 
DumpNotifierLocked(const std::vector<int32_t> & tokenVec,std::string & info)119 void DistributedAbilityManagerService::DumpNotifierLocked(const std::vector<int32_t>& tokenVec, std::string& info)
120 {
121     std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
122     for (const auto& token : tokenVec) {
123         info += ", ";
124         info += "token: ";
125         info += std::to_string(token);
126         if (callbackMap_.find(token) == callbackMap_.end()) {
127             continue;
128         }
129         if (callbackMap_[token] == nullptr) {
130             HILOGE("this ptr is null");
131             return;
132         }
133         if (!callbackMap_[token]->IsNotifierMapEmpty()) {
134             info += ", ";
135             info += "cbType: ";
136             if (callbackMap_[token]->GetNotifier(EVENT_CONNECT) != nullptr) {
137                 info += " ";
138                 info += EVENT_CONNECT;
139             }
140             if (callbackMap_[token]->GetNotifier(EVENT_DISCONNECT) != nullptr) {
141                 info += " ";
142                 info += EVENT_DISCONNECT;
143             }
144         }
145     }
146 }
147 
VerifyPermission(uint32_t accessToken,const std::string & permissionName) const148 bool DistributedAbilityManagerService::VerifyPermission(uint32_t accessToken, const std::string& permissionName) const
149 {
150     int32_t result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, permissionName);
151     if (result == Security::AccessToken::PermissionState::PERMISSION_DENIED) {
152         HILOGE("permission denied, permissionName:%{public}s", permissionName.c_str());
153         return false;
154     }
155     HILOGD("permission matched.");
156     return true;
157 }
158 
Register(const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams,int32_t & token)159 int32_t DistributedAbilityManagerService::Register(
160     const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams, int32_t& token)
161 {
162     HILOGD("called");
163     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
164     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
165         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
166         return DMS_PERMISSION_DENIED;
167     }
168     if (continuationExtraParams != nullptr) {
169         ContinuationMode continuationMode = continuationExtraParams->GetContinuationMode();
170         if (!IsContinuationModeValid(continuationMode)) {
171             return INVALID_CONTINUATION_MODE;
172         }
173     }
174     int32_t ret = RegisterWithoutExtraParam(token);
175     return ret;
176 }
177 
Unregister(int32_t token)178 int32_t DistributedAbilityManagerService::Unregister(int32_t token)
179 {
180     HILOGD("called");
181     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
182     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
183         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
184         return DMS_PERMISSION_DENIED;
185     }
186     if (!IsTokenRegistered(accessToken, token)) {
187         return TOKEN_HAS_NOT_REGISTERED;
188     }
189     // remove death recipient and update callbackMap_ by token
190     {
191         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
192         if (IsNotifierRegistered(token)) {
193             callbackMap_[token]->RemoveDeathRecipient(notifierDeathRecipient_);
194             callbackMap_.erase(token);
195         }
196     }
197     // update tokenMap_ by token
198     {
199         std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
200         for (auto iter = tokenMap_.begin(); iter != tokenMap_.end();) {
201             iter->second.erase(std::remove_if(iter->second.begin(), iter->second.end(),
202                 [token](int32_t n) { return n == token; }), iter->second.end());
203             if (iter->second.empty()) {
204                 tokenMap_.erase(iter++);
205                 break;
206             } else {
207                 iter++;
208             }
209         }
210     }
211     // disconnect to app when third-party app called unregister
212     (void)HandleDisconnectAbility();
213     return ERR_OK;
214 }
215 
RegisterDeviceSelectionCallback(int32_t token,const std::string & cbType,const sptr<IRemoteObject> & notifier)216 int32_t DistributedAbilityManagerService::RegisterDeviceSelectionCallback(
217     int32_t token, const std::string& cbType, const sptr<IRemoteObject>& notifier)
218 {
219     HILOGD("called");
220     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
221     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
222         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
223         return DMS_PERMISSION_DENIED;
224     }
225     if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
226         HILOGE("type: %{public}s not support!", cbType.c_str());
227         return UNKNOWN_CALLBACK_TYPE;
228     }
229     if (!IsTokenRegistered(accessToken, token)) {
230         return TOKEN_HAS_NOT_REGISTERED;
231     }
232     if (IsNotifierRegisteredLocked(token, cbType)) {
233         return CALLBACK_HAS_REGISTERED;
234     }
235     {
236         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
237         auto iter = callbackMap_.find(token);
238         if (iter != callbackMap_.end()) { // registered at least once
239             if (iter->second == nullptr) {
240                 return ERR_NULL_OBJECT;
241             }
242             iter->second->SetNotifier(cbType, notifier);
243         } else { // never registered
244             std::unique_ptr<NotifierInfo> notifierInfo = std::make_unique<NotifierInfo>();
245             notifierInfo->SetNotifier(cbType, notifier);
246             callbackMap_[token] = std::move(notifierInfo);
247             notifier->AddDeathRecipient(notifierDeathRecipient_);
248         }
249         HILOGD("token register success");
250     }
251     return ERR_OK;
252 }
253 
UnregisterDeviceSelectionCallback(int32_t token,const std::string & cbType)254 int32_t DistributedAbilityManagerService::UnregisterDeviceSelectionCallback(int32_t token, const std::string& cbType)
255 {
256     HILOGD("called");
257     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
258     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
259         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
260         return DMS_PERMISSION_DENIED;
261     }
262     if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
263         HILOGE("type: %{public}s not support!", cbType.c_str());
264         return UNKNOWN_CALLBACK_TYPE;
265     }
266     if (!IsTokenRegistered(accessToken, token)) {
267         return TOKEN_HAS_NOT_REGISTERED;
268     }
269     if (!IsNotifierRegisteredLocked(token, cbType)) {
270         return CALLBACK_HAS_NOT_REGISTERED;
271     }
272     {
273         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
274         auto iter = callbackMap_.find(token);
275         if (iter != callbackMap_.end()) {
276             iter->second->RemoveDeathRecipient(notifierDeathRecipient_, cbType);
277             iter->second->DeleteNotifier(cbType);
278             if (iter->second->IsNotifierMapEmpty()) {
279                 callbackMap_.erase(iter);
280             }
281         }
282     }
283     HILOGD("token unregister success");
284     return ERR_OK;
285 }
286 
UpdateConnectStatus(int32_t token,const std::string & deviceId,DeviceConnectStatus deviceConnectStatus)287 int32_t DistributedAbilityManagerService::UpdateConnectStatus(int32_t token, const std::string& deviceId,
288     DeviceConnectStatus deviceConnectStatus)
289 {
290     HILOGD("called");
291     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
292     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
293         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
294         return DMS_PERMISSION_DENIED;
295     }
296     if (deviceId.empty()) {
297         HILOGE("deviceId is empty");
298         return ERR_NULL_OBJECT;
299     }
300     if (!IsConnectStatusValid(deviceConnectStatus)) {
301         return INVALID_CONNECT_STATUS;
302     }
303     if (!IsTokenRegistered(accessToken, token)) {
304         return TOKEN_HAS_NOT_REGISTERED;
305     }
306     {
307         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
308         if (!IsNotifierRegistered(token)) {
309             return CALLBACK_HAS_NOT_REGISTERED;
310         }
311         std::shared_ptr<ConnectStatusInfo> connectStatusInfo =
312             std::make_shared<ConnectStatusInfo>(deviceId, deviceConnectStatus);
313         callbackMap_[token]->SetConnectStatusInfo(connectStatusInfo);
314     }
315     // sendRequest status(token, connectStatusInfo) to app by app proxy when appProxy_ is not null.
316     {
317         std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
318         if (appProxy_ != nullptr) {
319             HandleUpdateConnectStatus(token, deviceId, deviceConnectStatus);
320         }
321     }
322     return ERR_OK;
323 }
324 
StartDeviceManager(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)325 int32_t DistributedAbilityManagerService::StartDeviceManager(
326     int32_t token, const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
327 {
328     HILOGD("called");
329     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
330     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
331         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
332         return DMS_PERMISSION_DENIED;
333     }
334     if (continuationExtraParams != nullptr) {
335         ContinuationMode continuationMode = continuationExtraParams->GetContinuationMode();
336         if (!IsContinuationModeValid(continuationMode)) {
337             return INVALID_CONTINUATION_MODE;
338         }
339     }
340     if (!IsTokenRegistered(accessToken, token)) {
341         return TOKEN_HAS_NOT_REGISTERED;
342     }
343     {
344         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
345         if (!IsNotifierRegistered(token)) {
346             return CALLBACK_HAS_NOT_REGISTERED;
347         }
348     }
349     // 1. connect to app and get the app proxy if appProxy_ is null, otherwise start device manager directly.
350     {
351         std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
352         if (appProxy_ != nullptr) {
353             HandleStartDeviceManager(token, continuationExtraParams);
354             return ERR_OK;
355         }
356     }
357     int32_t errCode = ConnectAbility(token, continuationExtraParams);
358     if (errCode != ERR_OK) {
359         HILOGE("token connect to app failed");
360         return CONNECT_ABILITY_FAILED;
361     }
362     // 2. sendRequest data(token, filter, dmsStub, connectStatusInfo) to app by app proxy when connect callback.
363     return ERR_OK;
364 }
365 
RegisterWithoutExtraParam(int32_t & token)366 int32_t DistributedAbilityManagerService::RegisterWithoutExtraParam(int32_t& token)
367 {
368     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
369     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
370         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
371         return DMS_PERMISSION_DENIED;
372     }
373     if (IsExceededRegisterMaxNum(accessToken)) {
374         return REGISTER_EXCEED_MAX_TIMES;
375     }
376     int32_t tToken = -1;
377     {
378         std::lock_guard<std::mutex> tokenLock(tokenMutex_);
379         tToken = token_.load();
380         if (++tToken > MAX_TOKEN_NUM) {
381             tToken = 1;
382         }
383         token_.store(tToken);
384         // save at parameters
385         system::SetParameter(TOKEN_KEY, std::to_string(tToken));
386     }
387     // update tokenMap_
388     {
389         std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
390         tokenMap_[accessToken].emplace_back(tToken);
391     }
392     token = tToken;
393     return ERR_OK;
394 }
395 
StartDeviceManagerWithoutExtraParam(int32_t token)396 int32_t DistributedAbilityManagerService::StartDeviceManagerWithoutExtraParam(int32_t token)
397 {
398     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
399     if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
400         HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
401         return DMS_PERMISSION_DENIED;
402     }
403     if (!IsTokenRegistered(accessToken, token)) {
404         return TOKEN_HAS_NOT_REGISTERED;
405     }
406     {
407         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
408         if (!IsNotifierRegistered(token)) {
409             return CALLBACK_HAS_NOT_REGISTERED;
410         }
411     }
412     // 1. connect to app and get the app proxy if appProxy_ is null, otherwise start device manager directly.
413     {
414         std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
415         if (appProxy_ != nullptr) {
416             HandleStartDeviceManager(token, nullptr);
417             return ERR_OK;
418         }
419     }
420     int32_t errCode = ConnectAbility(token, nullptr);
421     if (errCode != ERR_OK) {
422         HILOGE("token connect to app failed");
423         return CONNECT_ABILITY_FAILED;
424     }
425     // 2. sendRequest data(token, filter, dmsStub, connectStatusInfo) to app by app proxy when connect callback.
426     return ERR_OK;
427 }
428 
ConnectAbility(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)429 int32_t DistributedAbilityManagerService::ConnectAbility(int32_t token,
430     const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
431 {
432     AAFwk::Want want;
433     want.SetAction(DMS_HIPLAY_ACTION);
434     int32_t activeAccountId = -1;
435 #ifdef OS_ACCOUNT_PART
436     std::vector<int32_t> ids;
437     int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
438     if (ret != ERR_OK || ids.empty()) {
439         return INVALID_PARAMETERS_ERR;
440     }
441     activeAccountId = ids[0];
442 #endif
443     AppExecFwk::ExtensionAbilityInfo extensionInfo;
444     if (!QueryExtensionAbilityInfo(activeAccountId, want, extensionInfo)) {
445         HILOGE("QueryExtensionAbilityInfo failed");
446         return CONNECT_ABILITY_FAILED;
447     }
448     if (connect_ == nullptr) {
449         connect_ = new AppConnectionStub(token, continuationExtraParams);
450     }
451     int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
452     if (errCode != ERR_OK) {
453         HILOGE("connect ability manager server failed, errCode=%{public}d", errCode);
454         return errCode;
455     }
456     errCode = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want,
457         iface_cast<AAFwk::IAbilityConnection>(connect_), this, activeAccountId);
458     if (errCode != ERR_OK) {
459         HILOGE("ConnectAbility failed");
460         connect_ = nullptr;
461         return CONNECT_ABILITY_FAILED;
462     }
463     return ERR_OK;
464 }
465 
QueryExtensionAbilityInfo(const int32_t & activeAccountId,const AAFwk::Want & want,AppExecFwk::ExtensionAbilityInfo & extensionInfo)466 bool DistributedAbilityManagerService::QueryExtensionAbilityInfo(const int32_t& activeAccountId,
467     const AAFwk::Want& want, AppExecFwk::ExtensionAbilityInfo& extensionInfo)
468 {
469     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
470     if (samgrProxy == nullptr) {
471         HILOGE("get samgr failed");
472         return false;
473     }
474     sptr<IRemoteObject> bmsProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
475     if (bmsProxy == nullptr) {
476         HILOGE("get bms from samgr failed");
477         return false;
478     }
479     auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bmsProxy);
480     if (bundleMgr == nullptr) {
481         HILOGE("bms iface_cast failed");
482         return false;
483     }
484     std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
485     std::string identity = IPCSkeleton::ResetCallingIdentity();
486     bundleMgr->QueryExtensionAbilityInfos(want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
487         | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_PERMISSION, activeAccountId, extensionInfos);
488     IPCSkeleton::SetCallingIdentity(identity);
489     if (extensionInfos.empty()) {
490         HILOGE("QueryExtensionAbilityInfo failed");
491         return false;
492     }
493     extensionInfo = extensionInfos.front();
494     if (extensionInfo.bundleName.empty() || extensionInfo.name.empty()) {
495         HILOGE("ExtensionAbilityInfo is empty.");
496         return false;
497     }
498     HILOGD("ExtensionAbilityInfo found, name=%{public}s.", extensionInfo.name.c_str());
499     return true;
500 }
501 
DisconnectAbility()502 int32_t DistributedAbilityManagerService::DisconnectAbility()
503 {
504     if (connect_ == nullptr) {
505         return ERR_NULL_OBJECT;
506     }
507     int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
508     if (errCode != ERR_OK) {
509         HILOGE("connect ability manager server failed, errCode=%{public}d", errCode);
510         return errCode;
511     }
512     errCode = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(
513         iface_cast<AAFwk::IAbilityConnection>(connect_));
514     connect_ = nullptr;
515     if (errCode != ERR_OK) {
516         HILOGE("DisconnectAbility failed");
517         return DISCONNECT_ABILITY_FAILED;
518     }
519     return ERR_OK;
520 }
521 
OnDeviceConnect(int32_t token,const std::vector<ContinuationResult> & continuationResults)522 int32_t DistributedAbilityManagerService::OnDeviceConnect(int32_t token,
523     const std::vector<ContinuationResult>& continuationResults)
524 {
525     // device connect callback to napi
526     if (!HandleDisconnectAbility()) {
527         return DISCONNECT_ABILITY_FAILED;
528     }
529     if (!IsNotifierRegisteredLocked(token, EVENT_CONNECT)) {
530         return CALLBACK_HAS_NOT_REGISTERED;
531     }
532     {
533         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
534         auto notifier = callbackMap_[token]->GetNotifier(EVENT_CONNECT);
535         if (!HandleDeviceConnect(notifier, continuationResults)) {
536             return INVALID_PARAMETERS_ERR;
537         }
538     }
539     return ERR_OK;
540 }
541 
OnDeviceDisconnect(int32_t token,const std::vector<ContinuationResult> & continuationResults)542 int32_t DistributedAbilityManagerService::OnDeviceDisconnect(int32_t token,
543     const std::vector<ContinuationResult>& continuationResults)
544 {
545     // device disconnect callback to napi
546     if (!HandleDisconnectAbility()) {
547         return DISCONNECT_ABILITY_FAILED;
548     }
549     if (!IsNotifierRegisteredLocked(token, EVENT_DISCONNECT)) {
550         return CALLBACK_HAS_NOT_REGISTERED;
551     }
552     {
553         std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
554         auto notifier = callbackMap_[token]->GetNotifier(EVENT_DISCONNECT);
555         if (!HandleDeviceDisconnect(notifier, continuationResults)) {
556             return INVALID_PARAMETERS_ERR;
557         }
558     }
559     return ERR_OK;
560 }
561 
OnDeviceCancel()562 int32_t DistributedAbilityManagerService::OnDeviceCancel()
563 {
564     // disconnect to app when app close the window.
565     if (!HandleDisconnectAbility()) {
566         return DISCONNECT_ABILITY_FAILED;
567     }
568     return ERR_OK;
569 }
570 
HandleDisconnectAbility()571 bool DistributedAbilityManagerService::HandleDisconnectAbility()
572 {
573     if (continuationHandler_ == nullptr) {
574         HILOGE("continuationHandler is null.");
575         return false;
576     }
577     auto func = [this]() {
578         HILOGD("HandleDisconnectAbility called.");
579         int32_t errCode = DisconnectAbility();
580         if (errCode != ERR_OK) {
581             HILOGE("DisconnectAbility errCode: %{public}d.", errCode);
582             return;
583         }
584     };
585     continuationHandler_->submit(func);
586     return true;
587 }
588 
IsExceededRegisterMaxNum(uint32_t accessToken)589 bool DistributedAbilityManagerService::IsExceededRegisterMaxNum(uint32_t accessToken)
590 {
591     std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
592     auto iter = tokenMap_.find(accessToken);
593     if (iter != tokenMap_.end() && iter->second.size() >= MAX_REGISTER_NUM) {
594         HILOGE("accessToken registered too much times");
595         return true;
596     }
597     return false;
598 }
599 
IsContinuationModeValid(ContinuationMode continuationMode)600 bool DistributedAbilityManagerService::IsContinuationModeValid(ContinuationMode continuationMode)
601 {
602     if (static_cast<int32_t>(continuationMode) < static_cast<int32_t>(ContinuationMode::COLLABORATION_SINGLE) ||
603         static_cast<int32_t>(continuationMode) > static_cast<int32_t>(ContinuationMode::COLLABORATION_MUTIPLE)) {
604         HILOGE("continuationMode is invalid");
605         return false;
606     }
607     return true;
608 }
609 
IsConnectStatusValid(DeviceConnectStatus deviceConnectStatus)610 bool DistributedAbilityManagerService::IsConnectStatusValid(DeviceConnectStatus deviceConnectStatus)
611 {
612     if (static_cast<int32_t>(deviceConnectStatus) < static_cast<int32_t>(DeviceConnectStatus::IDLE) ||
613         static_cast<int32_t>(deviceConnectStatus) > static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)) {
614         HILOGE("deviceConnectStatus is invalid");
615         return false;
616     }
617     return true;
618 }
619 
IsTokenRegistered(uint32_t accessToken,int32_t token)620 bool DistributedAbilityManagerService::IsTokenRegistered(uint32_t accessToken, int32_t token)
621 {
622     std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
623     auto iter = tokenMap_.find(accessToken);
624     if (iter == tokenMap_.end()) {
625         HILOGE("accessToken has not registered in token map.");
626         return false;
627     }
628     for (auto it = iter->second.begin(); it != iter->second.end(); it++) {
629         if (*it == token) {
630             return true;
631         }
632     }
633     HILOGE("token has not registered");
634     return false;
635 }
636 
IsNotifierRegistered(int32_t token)637 bool DistributedAbilityManagerService::IsNotifierRegistered(int32_t token)
638 {
639     // must be in callbackMapLock scope
640     auto iter = callbackMap_.find(token);
641     if (iter == callbackMap_.end()) {
642         HILOGE("accessToken has not registered in callback map.");
643         return false;
644     }
645     if (iter->second == nullptr) {
646         HILOGE("notifierInfo is nullptr");
647         return false;
648     }
649     return true;
650 }
651 
IsNotifierRegisteredLocked(int32_t token,const std::string & cbType)652 bool DistributedAbilityManagerService::IsNotifierRegisteredLocked(int32_t token, const std::string& cbType)
653 {
654     std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
655     if (!IsNotifierRegistered(token)) {
656         return false;
657     }
658     if (callbackMap_[token]->GetNotifier(cbType) != nullptr) {
659         HILOGD("token and cbType:%{public}s has already registered", cbType.c_str());
660         return true;
661     }
662     HILOGE("token and cbType:%{public}s has not registered", cbType.c_str());
663     return false;
664 }
665 
HandleDeviceConnect(const sptr<IRemoteObject> & notifier,const std::vector<ContinuationResult> & continuationResults)666 bool DistributedAbilityManagerService::HandleDeviceConnect(const sptr<IRemoteObject>& notifier,
667     const std::vector<ContinuationResult>& continuationResults)
668 {
669     if (continuationHandler_ == nullptr) {
670         HILOGE("continuationHandler_ is nullptr");
671         return false;
672     }
673     if (notifier == nullptr) {
674         HILOGE("notifier is nullptr");
675         return false;
676     }
677     auto func = [notifier, continuationResults]() {
678         HILOGD("HandleDeviceConnect called.");
679         auto proxy = std::make_unique<DeviceSelectionNotifierProxy>(notifier);
680         proxy->OnDeviceConnect(continuationResults);
681     };
682     continuationHandler_->submit(func);
683     return true;
684 }
685 
HandleDeviceDisconnect(const sptr<IRemoteObject> & notifier,const std::vector<ContinuationResult> & continuationResults)686 bool DistributedAbilityManagerService::HandleDeviceDisconnect(const sptr<IRemoteObject>& notifier,
687     const std::vector<ContinuationResult>& continuationResults)
688 {
689     if (continuationHandler_ == nullptr) {
690         HILOGE("continuationHandler_ is nullptr");
691         return false;
692     }
693     if (notifier == nullptr) {
694         HILOGE("notifier is nullptr");
695         return false;
696     }
697     auto func = [notifier, continuationResults]() {
698         HILOGD("HandleDeviceDisconnect called.");
699         auto proxy = std::make_unique<DeviceSelectionNotifierProxy>(notifier);
700         proxy->OnDeviceDisconnect(continuationResults);
701     };
702     continuationHandler_->submit(func);
703     return true;
704 }
705 
ScheduleStartDeviceManager(const sptr<IRemoteObject> & appProxy,int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)706 void DistributedAbilityManagerService::ScheduleStartDeviceManager(const sptr<IRemoteObject>& appProxy, int32_t token,
707     const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
708 {
709     std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
710     appProxy_ = appProxy;
711     if (appProxy_ == nullptr) {
712         return;
713     }
714     HandleStartDeviceManager(token, continuationExtraParams);
715 }
716 
HandleStartDeviceManager(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)717 void DistributedAbilityManagerService::HandleStartDeviceManager(int32_t token,
718     const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
719 {
720     if (continuationHandler_ == nullptr) {
721         HILOGE("continuationHandler_ is nullptr");
722         return;
723     }
724     auto func = [this, token, continuationExtraParams, appProxy = appProxy_]() {
725         HILOGD("HandleStartDeviceManager called.");
726         MessageParcel data;
727         if (!data.WriteInterfaceToken(HIPLAY_PANEL_INTERFACE_TOKEN)) {
728             HILOGE("WriteInterfaceToken failed");
729             return;
730         }
731         PARCEL_WRITE_HELPER_NORET(data, Int32, token);
732         if (continuationExtraParams == nullptr) {
733             PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
734         } else {
735             PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_OBJECT);
736             PARCEL_WRITE_HELPER_NORET(data, Parcelable, continuationExtraParams.get());
737         }
738         sptr<AppDeviceCallbackStub> callback(new AppDeviceCallbackStub());
739         PARCEL_WRITE_HELPER_NORET(data, RemoteObject, callback);
740         // query whether the connect status needs to be send
741         {
742             std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
743             if (IsNotifierRegistered(token)) {
744                 std::shared_ptr<ConnectStatusInfo> connectStatusInfo = callbackMap_[token]->GetConnectStatusInfo();
745                 if (connectStatusInfo == nullptr) {
746                     PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
747                 } else {
748                     PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_OBJECT);
749                     // use u16string, because send to app
750                     PARCEL_WRITE_HELPER_NORET(data, String16, Str8ToStr16(connectStatusInfo->GetDeviceId()));
751                     PARCEL_WRITE_HELPER_NORET(data, Int32,
752                         static_cast<int32_t>(connectStatusInfo->GetDeviceConnectStatus()));
753                 }
754             } else {
755                 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
756             }
757         }
758         MessageParcel reply;
759         MessageOption option;
760         if (appProxy == nullptr) {
761             HILOGE("appProxy is nullptr");
762             return;
763         }
764         int32_t result = appProxy->SendRequest(START_DEVICE_MANAGER_CODE, data, reply, option);
765         HILOGD("result is %{public}d", result);
766     };
767     continuationHandler_->submit(func);
768 }
769 
HandleUpdateConnectStatus(int32_t token,std::string deviceId,const DeviceConnectStatus & deviceConnectStatus)770 void DistributedAbilityManagerService::HandleUpdateConnectStatus(int32_t token, std::string deviceId,
771     const DeviceConnectStatus& deviceConnectStatus)
772 {
773     if (continuationHandler_ == nullptr) {
774         HILOGE("continuationHandler_ is nullptr");
775         return;
776     }
777     auto func = [this, token, deviceId, deviceConnectStatus, appProxy = appProxy_]() {
778         HILOGD("HandleUpdateConnectStatus called.");
779         MessageParcel data;
780         if (!data.WriteInterfaceToken(HIPLAY_PANEL_INTERFACE_TOKEN)) {
781             HILOGE("WriteInterfaceToken failed");
782             return;
783         }
784         PARCEL_WRITE_HELPER_NORET(data, Int32, token);
785         // use u16string, because send to app
786         PARCEL_WRITE_HELPER_NORET(data, String16, Str8ToStr16(deviceId));
787         PARCEL_WRITE_HELPER_NORET(data, Int32, static_cast<int32_t>(deviceConnectStatus));
788         MessageParcel reply;
789         MessageOption option;
790         if (appProxy == nullptr) {
791             HILOGE("appProxy is nullptr");
792             return;
793         }
794         int32_t result = appProxy->SendRequest(UPDATE_CONNECT_STATUS_CODE, data, reply, option);
795         HILOGD("result is %{public}d", result);
796     };
797     continuationHandler_->submit(func);
798 }
799 
QueryTokenByNotifier(const sptr<IRemoteObject> & notifier,int32_t & token)800 bool DistributedAbilityManagerService::QueryTokenByNotifier(const sptr<IRemoteObject>& notifier, int32_t& token)
801 {
802     std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
803     for (auto iter = callbackMap_.begin(); iter != callbackMap_.end(); iter++) {
804         if (iter->second == nullptr) {
805             return false;
806         }
807         if (iter->second->QueryNotifier(notifier)) {
808             token = iter->first;
809             return true;
810         }
811     }
812     return false;
813 }
814 
ProcessNotifierDied(const sptr<IRemoteObject> & notifier)815 void DistributedAbilityManagerService::ProcessNotifierDied(const sptr<IRemoteObject>& notifier)
816 {
817     // update cache when third-party app died
818     if (notifier == nullptr) {
819         return;
820     }
821     HandleNotifierDied(notifier);
822 }
823 
HandleNotifierDied(const sptr<IRemoteObject> & notifier)824 void DistributedAbilityManagerService::HandleNotifierDied(const sptr<IRemoteObject>& notifier)
825 {
826     if (continuationHandler_ == nullptr) {
827         HILOGE("continuationHandler_ is nullptr");
828         return;
829     }
830     auto func = [this, notifier] () {
831         HILOGD("HandleNotifierDied called.");
832         // query token in callbackMap_ by notifier
833         int32_t token = -1;
834         if (!QueryTokenByNotifier(notifier, token)) {
835             HILOGE("QueryTokenByNotifier failed");
836             return;
837         }
838         // remove death recipient and update callbackMap_ by token
839         {
840             std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
841             if (IsNotifierRegistered(token)) {
842                 callbackMap_[token]->RemoveDeathRecipient(notifierDeathRecipient_);
843                 callbackMap_.erase(token);
844             }
845         }
846         // update tokenMap_ by token
847         {
848             std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
849             for (auto iter = tokenMap_.begin(); iter != tokenMap_.end();) {
850                 iter->second.erase(std::remove_if(iter->second.begin(), iter->second.end(),
851                     [token](int32_t n) { return n == token; }), iter->second.end());
852                 if (iter->second.empty()) {
853                     tokenMap_.erase(iter++);
854                     break;
855                 } else {
856                     iter++;
857                 }
858             }
859         }
860         // disconnect to app when third-party app died
861         (void)HandleDisconnectAbility();
862     };
863     continuationHandler_->submit(func);
864 }
865 } // namespace DistributedSchedule
866 } // namespace OHOS
867