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