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