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