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