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