1  /*
2   * Copyright (c) 2023-2024 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 "mission/dms_continue_send_manager.h"
17  
18  #include <sys/prctl.h>
19  
20  #include "adapter/dnetwork_adapter.h"
21  #include "adapter/mmi_adapter.h"
22  #include "datetime_ex.h"
23  #include "datashare_manager.h"
24  #include "dfx/distributed_radar.h"
25  #include "distributed_sched_adapter.h"
26  #include "distributed_sched_utils.h"
27  #include "dsched_data_buffer.h"
28  #include "dtbschedmgr_device_info_storage.h"
29  #include "dtbschedmgr_log.h"
30  #include "mission/dms_continue_recv_manager.h"
31  #include "mission/wifi_state_adapter.h"
32  #include "parcel_helper.h"
33  #include "softbus_adapter/softbus_adapter.h"
34  #include "switch_status_dependency.h"
35  
36  namespace OHOS {
37  namespace DistributedSchedule {
38  namespace {
39  constexpr int32_t INDEX_2 = 2;
40  constexpr int32_t INDEX_3 = 3;
41  constexpr int32_t CANCEL_FOCUSED_DELAYED = 60000;
42  constexpr int32_t SCREEN_OFF_DELAY_TIME = 10000;
43  constexpr int64_t TIME_DELAYED = 500; // determines whether normal unfocused or lockoff
44  const std::string TAG = "DMSContinueSendMgr";
45  const std::string TIMEOUT_UNFOCUSED_TASK = "timeout_unfocused_task";
46  const std::string SCREEN_OFF_UNFOCUSED_TASK = "screen_off_unfocused_task";
47  }
48  
49  IMPLEMENT_SINGLE_INSTANCE(DMSContinueSendMgr);
50  
Init()51  void DMSContinueSendMgr::Init()
52  {
53      HILOGI("Init start");
54      if (eventHandler_ != nullptr) {
55          HILOGI("Already inited, end.");
56          return;
57      }
58      {
59          MMIAdapter::GetInstance().Init();
60          SoftbusAdapter::GetInstance().Init();
61          screenOffHandler_ = std::make_shared<ScreenOffHandler>();
62  
63          eventThread_ = std::thread(&DMSContinueSendMgr::StartEvent, this);
64          std::unique_lock<std::mutex> lock(eventMutex_);
65          eventCon_.wait(lock, [this] {
66              return eventHandler_ != nullptr;
67          });
68      }
69  
70      int32_t missionId = GetCurrentMissionId();
71      if (missionId <= 0) {
72          HILOGW("GetCurrentMissionId failed, init end. ret: %{public}d", missionId);
73          return;
74      }
75      NotifyMissionFocused(missionId, FocusedReason::INIT);
76      HILOGI("Init end");
77  }
78  
UnInit()79  void DMSContinueSendMgr::UnInit()
80  {
81      HILOGI("UnInit start");
82      MMIAdapter::GetInstance().UnInit();
83      SoftbusAdapter::GetInstance().UnInit();
84      if (eventHandler_ != nullptr && eventHandler_->GetEventRunner() != nullptr) {
85          eventHandler_->GetEventRunner()->Stop();
86          eventThread_.join();
87          eventHandler_ = nullptr;
88      } else {
89          HILOGE("eventHandler_ is nullptr");
90      }
91      HILOGI("UnInit end");
92  }
93  
GetCurrentMissionId()94  int32_t DMSContinueSendMgr::GetCurrentMissionId()
95  {
96      HILOGI("GetCurrentMission begin");
97      auto abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
98      if (abilityMgr == nullptr) {
99          HILOGE("abilityMgr is nullptr");
100          return INVALID_PARAMETERS_ERR;
101      }
102  
103      sptr<IRemoteObject> token;
104      int ret = abilityMgr->GetTopAbility(token);
105      if (ret != ERR_OK || token == nullptr) {
106          HILOGE("GetTopAbility failed, ret: %{public}d", ret);
107          return INVALID_MISSION_ID;
108      }
109      int32_t missionId = INVALID_MISSION_ID;
110      abilityMgr->GetMissionIdByToken(token, missionId);
111      return missionId;
112  }
113  
PostUnfocusedTaskWithDelay(const int32_t missionId,UnfocusedReason reason)114  void DMSContinueSendMgr::PostUnfocusedTaskWithDelay(const int32_t missionId, UnfocusedReason reason)
115  {
116      HILOGI("called, missionId: %{public}d, reason: %{public}d", missionId, reason);
117      if (eventHandler_ == nullptr) {
118          HILOGE("eventHandler_ is nullptr");
119          return;
120      }
121      if (reason == UnfocusedReason::TIMEOUT) {
122          auto funcOut = [this, missionId]() {
123              DealUnfocusedBusiness(missionId, UnfocusedReason::TIMEOUT);
124          };
125          std::string timeoutTaskName = TIMEOUT_UNFOCUSED_TASK + std::to_string(missionId);
126          eventHandler_->RemoveTask(timeoutTaskName);
127          eventHandler_->PostTask(funcOut, timeoutTaskName, CANCEL_FOCUSED_DELAYED);
128      } else if (reason == UnfocusedReason::SCREENOFF) {
129          auto funcOff = [this]() {
130              SendScreenOffEvent(DMS_UNFOCUSED_TYPE);
131          };
132          std::string scrOffTaskName = SCREEN_OFF_UNFOCUSED_TASK + std::to_string(missionId);
133          eventHandler_->RemoveTask(scrOffTaskName);
134          eventHandler_->PostTask(funcOff, scrOffTaskName, SCREEN_OFF_DELAY_TIME);
135      }
136  }
137  
NotifyMissionFocused(const int32_t missionId,FocusedReason reason)138  void DMSContinueSendMgr::NotifyMissionFocused(const int32_t missionId, FocusedReason reason)
139  {
140      HILOGI("NotifyMissionFocused called, missionId: %{public}d, reason: %{public}d", missionId, reason);
141      if (reason <= FocusedReason::MIN || reason >= FocusedReason::MAX) {
142          HILOGI("Unknown focusedReason, no need to deal NotifyMissionFocused");
143          return;
144      }
145      if (!WifiStateAdapter::GetInstance().IsWifiActive()) {
146          HILOGE("wifi is not activated");
147          return;
148      }
149      auto feedfunc = [this, missionId, reason]() {
150          int32_t newMissionId = missionId;
151          if (reason == FocusedReason::MMI) {
152              newMissionId = info_.currentMissionId;
153          }
154          if (reason == FocusedReason::NORMAL && screenOffHandler_ != nullptr) {
155              screenOffHandler_->ClearScreenOffInfo();
156          }
157          DealFocusedBusiness(newMissionId, reason);
158          if (newMissionId == info_.currentMissionId && info_.currentIsContinuable) {
159              PostUnfocusedTaskWithDelay(newMissionId, UnfocusedReason::TIMEOUT);
160          }
161      };
162  
163      if (eventHandler_ == nullptr) {
164          HILOGE("eventHandler_ is nullptr");
165          return;
166      }
167      eventHandler_->RemoveTask(TIMEOUT_UNFOCUSED_TASK + std::to_string(missionId));
168      eventHandler_->RemoveTask(SCREEN_OFF_UNFOCUSED_TASK + std::to_string(missionId));
169      eventHandler_->PostTask(feedfunc);
170  }
171  
NotifyMissionUnfocused(const int32_t missionId,UnfocusedReason reason)172  void DMSContinueSendMgr::NotifyMissionUnfocused(const int32_t missionId, UnfocusedReason reason)
173  {
174      HILOGI("NotifyMissionUnfocused start, missionId: %{public}d, reason: %{public}d", missionId, reason);
175      if (reason <= UnfocusedReason::MIN || reason >= UnfocusedReason::MAX) {
176          HILOGE("unknown unfocused reason!");
177          return;
178      }
179      auto feedfunc = [this, missionId, reason]() {
180          DealUnfocusedBusiness(missionId, reason);
181      };
182      if (eventHandler_ != nullptr) {
183          eventHandler_->RemoveTask(TIMEOUT_UNFOCUSED_TASK + std::to_string(missionId));
184          eventHandler_->PostTask(feedfunc);
185      } else {
186          HILOGE("eventHandler_ is nullptr");
187      }
188  }
189  
GetMissionIdByBundleName(const std::string & bundleName,int32_t & missionId)190  int32_t DMSContinueSendMgr::GetMissionIdByBundleName(const std::string& bundleName, int32_t& missionId)
191  {
192      HILOGI("start, bundleName: %{public}s", bundleName.c_str());
193      std::lock_guard<std::mutex> focusedMissionMapLock(eventMutex_);
194      auto iterItem = focusedMission_.find(bundleName);
195      if (iterItem != focusedMission_.end()) {
196          missionId = iterItem->second;
197          HILOGI("get missionId end, missionId: %{public}d", missionId);
198          return ERR_OK;
199      }
200      HILOGW("get iterItem failed from focusedMission_, try screenOffHandler_");
201      if (screenOffHandler_ != nullptr && bundleName == screenOffHandler_->GetBundleName()) {
202          missionId = screenOffHandler_->GetMissionId();
203          HILOGI("get missionId end, missionId: %{public}d", missionId);
204          return ERR_OK;
205      }
206      HILOGW("get bundleName failed from screenOffHandler_");
207      if (bundleName == lastFocusedMissionInfo_.bundleName) {
208          missionId = lastFocusedMissionInfo_.missionId;
209          HILOGI("get missionId end, missionId: %{public}d", missionId);
210          return ERR_OK;
211      }
212      return MISSION_NOT_FOCUSED;
213  }
214  
StartEvent()215  void DMSContinueSendMgr::StartEvent()
216  {
217      HILOGI("StartEvent start");
218      prctl(PR_SET_NAME, CONTINUE_MANAGER.c_str());
219      auto runner = AppExecFwk::EventRunner::Create(false);
220      {
221          std::lock_guard<std::mutex> lock(eventMutex_);
222          eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
223      }
224      eventCon_.notify_one();
225      if (runner != nullptr) {
226          runner->Run();
227      } else {
228          HILOGE("runner is null");
229      }
230      HILOGI("StartEvent end");
231  }
232  
SendSoftbusEvent(uint16_t bundleNameId,uint8_t continueTypeId,uint8_t type)233  int32_t DMSContinueSendMgr::SendSoftbusEvent(uint16_t bundleNameId, uint8_t continueTypeId, uint8_t type)
234  {
235      HILOGD("SendSoftbusEvent start, bundleNameId: %{public}u, continueTypeId: %{public}u",
236          bundleNameId, continueTypeId);
237      std::shared_ptr<DSchedDataBuffer> buffer = std::make_shared<DSchedDataBuffer>(DMS_SEND_LEN);
238      if (buffer->Data() == nullptr || buffer->Size() < DMS_SEND_LEN) {
239          HILOGE("Failed to initialize DSchedDataBuffer");
240          return INVALID_PARAMETERS_ERR;
241      }
242      buffer->Data()[0] = (type << CONTINUE_SHIFT_04) | DMS_DATA_LEN;
243      buffer->Data()[1] = (bundleNameId >> CONTINUE_SHIFT_08) & DMS_0XFF;
244      buffer->Data()[INDEX_2] = bundleNameId & DMS_0XFF;
245      buffer->Data()[INDEX_3] = continueTypeId & DMS_0XFF;
246  
247      int32_t ret = SoftbusAdapter::GetInstance().SendSoftbusEvent(buffer);
248      HILOGD("SendSoftbusEvent end. Result: %{public}d", ret);
249      return ret;
250  }
251  
AddMMIListener()252  void DMSContinueSendMgr::AddMMIListener()
253  {
254      if (mmiMonitorId_ >= 0) {
255          HILOGD("MMI listener already exist, monitor id: %{public}d", mmiMonitorId_);
256          return;
257      }
258      mmiMonitorId_ = MMIAdapter::GetInstance().AddMMIListener();
259      if (mmiMonitorId_ < 0) {
260          HILOGW("Add MMI listener failed, ret: %{public}d", mmiMonitorId_);
261          return;
262      }
263      HILOGD("MMI listener has been added, monitor id: %{public}d", mmiMonitorId_);
264  }
265  
RemoveMMIListener()266  void DMSContinueSendMgr::RemoveMMIListener()
267  {
268      if (mmiMonitorId_ < 0) {
269          HILOGI("No MMI listener to be removed, monitor id: %{public}d", mmiMonitorId_);
270          return;
271      }
272      MMIAdapter::GetInstance().RemoveMMIListener(mmiMonitorId_);
273      HILOGI("MMI listener has been removed, monitor id: %{public}d", mmiMonitorId_);
274  
275      mmiMonitorId_ = INVALID_MISSION_ID;
276      return;
277  }
278  
DealFocusedBusiness(const int32_t missionId,FocusedReason reason)279  int32_t DMSContinueSendMgr::DealFocusedBusiness(const int32_t missionId, FocusedReason reason)
280  {
281      HILOGI("DealFocusedBusiness start, missionId: %{public}d", missionId);
282      AAFwk::MissionInfo info;
283      auto abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
284      if (abilityMgr != nullptr) {
285          int32_t ret = abilityMgr->GetMissionInfo("", missionId, info);
286          if (ret != ERR_OK) {
287              HILOGE("get missionInfo failed, missionId: %{public}d, ret: %{public}d", missionId, ret);
288              return ret;
289          }
290      } else {
291          HILOGE("abilityMgr is null");
292          return INVALID_PARAMETERS_ERR;
293      }
294      bool isMissionContinuable = info.continuable;
295      {
296          std::lock_guard<std::mutex> currentMissionIdLock(eventMutex_);
297          info_.currentMissionId = missionId;
298          info_.currentIsContinuable = isMissionContinuable;
299      }
300      if (!isMissionContinuable) {
301          HILOGI("Mission is not continuable, task abort, missionId: %{public}d", missionId);
302          return REMOTE_DEVICE_BIND_ABILITY_ERR;
303      }
304      std::string bundleName = info.want.GetBundle();
305      if (!CheckBundleContinueConfig(bundleName)) {
306          HILOGI("App does not allow continue in config file, bundle name %{public}s, missionId: %{public}d",
307              bundleName.c_str(), missionId);
308          return REMOTE_DEVICE_BIND_ABILITY_ERR;
309      }
310      focusedMission_[bundleName] = missionId;
311  
312      std::string abilityName = info.want.GetElement().GetAbilityName();
313      focusedMissionAbility_[missionId] = abilityName;
314      UpdateContinueLaunchMission(info);
315  
316      if (info.continueState != AAFwk::ContinueState::CONTINUESTATE_ACTIVE) {
317          HILOGE("Mission continue state set to INACTIVE. Broadcast task abort.");
318          return INVALID_PARAMETERS_ERR;
319      }
320  #ifdef SUPPORT_MULTIMODALINPUT_SERVICE
321      if (reason != FocusedReason::MMI) {
322          AddMMIListener();
323      }
324  #endif
325      if (!SwitchStatusDependency::GetInstance().IsContinueSwitchOn()) { return DMS_PERMISSION_DENIED;}
326      int32_t ret = FocusedBusinessSendEvent(bundleName, abilityName);
327      HILOGI("DealFocusedBusiness end");
328      return ret;
329  }
330  
FocusedBusinessSendEvent(std::string bundleName,const std::string & abilityName)331  int32_t DMSContinueSendMgr::FocusedBusinessSendEvent(std::string bundleName, const std::string& abilityName)
332  {
333      uint16_t bundleNameId = 0;
334      int32_t ret = BundleManagerInternal::GetBundleNameId(bundleName, bundleNameId);
335      if (ret != ERR_OK) {
336          HILOGE("Get focused bundleNameId failed, bundleNameId: %{public}u, ret: %{public}d", bundleNameId, ret);
337          return ret;
338      }
339  
340      uint8_t continueTypeId = 0;
341      ret = BundleManagerInternal::GetContinueTypeId(bundleName, abilityName, continueTypeId);
342      if (ret != ERR_OK) {
343          HILOGE("Get focused contineTypeId failed, contineTypeId: %{public}u, ret: %{public}d", continueTypeId, ret);
344          return ret;
345      }
346  
347      ret = SendSoftbusEvent(bundleNameId, continueTypeId, DMS_FOCUSED_TYPE);
348      if (ret != ERR_OK) {
349          HILOGE("SendSoftbusEvent focused failed, ret: %{public}d", ret);
350      }
351      return ret;
352  }
353  
CheckContinueState(const int32_t missionId)354  int32_t DMSContinueSendMgr::CheckContinueState(const int32_t missionId)
355  {
356      auto abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
357      if (abilityMgr == nullptr) {
358          HILOGE("abilityMgr is null");
359          return INVALID_PARAMETERS_ERR;
360      }
361  
362      AAFwk::MissionInfo info;
363      int32_t ret = abilityMgr->GetMissionInfo("", missionId, info);
364      if (ret != ERR_OK) {
365          HILOGE("get missionInfo failed, missionId: %{public}d, ret: %{public}d", missionId, ret);
366          return INVALID_PARAMETERS_ERR;
367      }
368      if (info.continueState != AAFwk::ContinueState::CONTINUESTATE_ACTIVE) {
369          HILOGE("Mission continue state set to INACTIVE. Broadcast task abort.");
370          return INVALID_PARAMETERS_ERR;
371      }
372      return ERR_OK;
373  }
374  
DealUnfocusedBusiness(const int32_t missionId,UnfocusedReason reason)375  int32_t DMSContinueSendMgr::DealUnfocusedBusiness(const int32_t missionId, UnfocusedReason reason)
376  {
377      HILOGI("DealUnfocusedBusiness start, missionId: %{public}d", missionId);
378      std::string bundleName;
379      int32_t ret = GetBundleNameByMissionId(missionId, bundleName);
380      if (ret != ERR_OK) {
381          HILOGI("Get bundleName failed, missionId: %{public}d, ret: %{public}d", missionId, ret);
382          return ret;
383      }
384      HILOGI("Get bundleName success, mission is continuable, missionId: %{public}d, bundleName: %{public}s",
385          missionId, bundleName.c_str());
386      std::string abilityName;
387      ret = GetAbilityNameByMissionId(missionId, abilityName);
388      if (ret != ERR_OK) {
389          HILOGE("get abilityName failed, missionId: %{public}d, ret: %{public}d", missionId, ret);
390          return ret;
391      }
392      if (reason != UnfocusedReason::TIMEOUT) {
393          if (!IsContinue(missionId, bundleName)) {
394              HILOGE("Not current mission to be continued, missionId: %{public}d", missionId);
395              EraseFocusedMission(bundleName, missionId, reason);
396              return NO_MISSION_INFO_FOR_MISSION_ID;
397          }
398  #ifdef SUPPORT_MULTIMODALINPUT_SERVICE
399          RemoveMMIListener();
400  #endif
401      }
402      uint16_t bundleNameId = 0;
403      uint8_t continueTypeId = 0;
404      ret = GetAccessTokenIdSendEvent(bundleName, reason, bundleNameId, continueTypeId);
405      if (ret != ERR_OK) {
406          HILOGE("GetAccessTokenIdSendEvent failed");
407          EraseFocusedMission(bundleName, missionId, reason);
408          return ret;
409      }
410      EraseFocusedMission(bundleName, missionId, reason);
411      if (reason == UnfocusedReason::NORMAL && screenOffHandler_ != nullptr) {
412          screenOffHandler_->SetScreenOffInfo(missionId, bundleName, bundleNameId, abilityName);
413      }
414      HILOGI("DealUnfocusedBusiness end");
415      return ERR_OK;
416  }
417  
EraseFocusedMission(const std::string & bundleName,const int32_t & missionId,const UnfocusedReason & reason)418  void DMSContinueSendMgr::EraseFocusedMission(const std::string& bundleName, const int32_t& missionId,
419      const UnfocusedReason& reason)
420  {
421      if (reason != UnfocusedReason::TIMEOUT) {
422          std::lock_guard<std::mutex> focusedMissionMapLock(eventMutex_);
423          focusedMission_.erase(bundleName);
424          focusedMissionAbility_.erase(missionId);
425          lastFocusedMissionInfo_ = { missionId, bundleName };
426      }
427  }
428  
SendScreenOffEvent(uint8_t type)429  int32_t DMSContinueSendMgr::SendScreenOffEvent(uint8_t type)
430  {
431      if (screenOffHandler_ == nullptr) {
432          HILOGE("screenOffHandler_ is nullptr");
433          return INVALID_PARAMETERS_ERR;
434      }
435      int32_t missionId = screenOffHandler_->GetMissionId();
436      std::string bundleName = screenOffHandler_->GetBundleName();
437      uint16_t bundleNameId = screenOffHandler_->GetAccessTokenId();
438      std::string abilityName = screenOffHandler_->GetAbilityName();
439  
440      HILOGI("start, type: %{public}d, missionId: %{public}d, bundleName: %{public}s, bundleNameId: %{public}u",
441          type, missionId, bundleName.c_str(), bundleNameId);
442      if (!CheckBundleContinueConfig(bundleName)) {
443          HILOGI("App does not allow continue in config file, bundle name %{public}s, missionId: %{public}d",
444              bundleName.c_str(), missionId);
445          return REMOTE_DEVICE_BIND_ABILITY_ERR;
446      }
447  
448      if (!DataShareManager::GetInstance().IsCurrentContinueSwitchOn()) {
449          HILOGE("ContinueSwitch status is off");
450          return DMS_PERMISSION_DENIED;
451      }
452  
453      uint8_t continueTypeId = 0;
454      int32_t ret = BundleManagerInternal::GetContinueTypeId(bundleName, abilityName, continueTypeId);
455      if (ret != ERR_OK) {
456          HILOGE("Get focused contineTypeId failed, abilityName: %{public}s, ret: %{public}d", abilityName.c_str(), ret);
457          return ret;
458      }
459  
460      ret = SendSoftbusEvent(bundleNameId, continueTypeId, type);
461      if (ret != ERR_OK) {
462          HILOGE("SendSoftbusEvent unfocused failed, ret: %{public}d", ret);
463      }
464      HILOGI("end");
465      return ERR_OK;
466  }
467  
GetBundleNameByMissionId(const int32_t missionId,std::string & bundleName)468  int32_t DMSContinueSendMgr::GetBundleNameByMissionId(const int32_t missionId, std::string& bundleName)
469  {
470      for (auto iterItem = focusedMission_.begin(); iterItem != focusedMission_.end(); iterItem++) {
471          if (iterItem->second == missionId) {
472              bundleName = iterItem->first;
473              return ERR_OK;
474          }
475      }
476      return INVALID_PARAMETERS_ERR;
477  }
478  
GetBundleNameByScreenOffInfo(const int32_t missionId,std::string & bundleName)479  int32_t DMSContinueSendMgr::GetBundleNameByScreenOffInfo(const int32_t missionId, std::string& bundleName)
480  {
481      if (screenOffHandler_ != nullptr && missionId == screenOffHandler_->GetMissionId()) {
482          bundleName = screenOffHandler_->GetBundleName();
483          if (bundleName.empty()) {
484              HILOGE("get bundleName failed from screenOffHandler");
485              return INVALID_PARAMETERS_ERR;
486          }
487          HILOGI("get missionId end, bundleName: %{public}s", bundleName.c_str());
488          return ERR_OK;
489      }
490      HILOGE("get bundleName failed from screenOffHandler");
491      return INVALID_PARAMETERS_ERR;
492  }
493  
GetAbilityNameByMissionId(const int32_t missionId,std::string & abilityName)494  int32_t DMSContinueSendMgr::GetAbilityNameByMissionId(const int32_t missionId, std::string& abilityName)
495  {
496      HILOGI("start, missionId: %{public}d", missionId);
497      std::lock_guard<std::mutex> focusedMissionAbilityMapLock(eventMutex_);
498      auto iterItem = focusedMissionAbility_.find(missionId);
499      if (iterItem != focusedMissionAbility_.end()) {
500          abilityName = iterItem->second;
501          HILOGI("get missionId end, missionId: %{public}d", missionId);
502          return ERR_OK;
503      }
504      HILOGW("get iterItem failed from focusedMissionAbility_, try screenOffHandler_");
505      if (screenOffHandler_ != nullptr && missionId == screenOffHandler_->GetMissionId()) {
506          abilityName = screenOffHandler_->GetAbilityName();
507          HILOGI("get missionId end, abilityName: %{public}s", abilityName.c_str());
508          return ERR_OK;
509      }
510      HILOGE("get abilityName failed from screenOffHandler_");
511      return INVALID_PARAMETERS_ERR;
512  }
513  
IsContinue(const int32_t & missionId,const std::string & bundleName)514  bool DMSContinueSendMgr::IsContinue(const int32_t& missionId, const std::string& bundleName)
515  {
516      if (missionId != info_.currentMissionId && info_.currentIsContinuable) {
517          /*missionId and currentMissionId are not equal but currentMission can change,
518              continue to not send unfocus broadcast*/
519          HILOGI("mission is not continue, missionId: %{public}d, currentMissionId: %{public}d",
520              missionId, info_.currentMissionId);
521          return false;
522      }
523      /*missionId and currentMissionId are equal, or missionId and currentMissionId are not equal
524          and currentIsContinuable not change, continue to send unfocus broadcast*/
525      HILOGI("mission is continue, missionId: %{public}d, currentMissionId: %{public}d",
526          missionId, info_.currentMissionId);
527      return true;
528  }
529  
SetMissionContinueState(const int32_t missionId,const AAFwk::ContinueState & state)530  int32_t DMSContinueSendMgr::SetMissionContinueState(const int32_t missionId,
531      const AAFwk::ContinueState &state)
532  {
533      HILOGI("SetMissionContinueState start, missionId: %{public}d, state: %{public}d", missionId, state);
534      auto feedfunc = [this, missionId, state]() {
535          DealSetMissionContinueStateBusiness(missionId, state);
536          if (state == AAFwk::ContinueState::CONTINUESTATE_ACTIVE && missionId == info_.currentMissionId &&
537              info_.currentIsContinuable) {
538              PostUnfocusedTaskWithDelay(missionId, UnfocusedReason::TIMEOUT);
539          }
540      };
541      if (eventHandler_ != nullptr) {
542          eventHandler_->RemoveTask(TIMEOUT_UNFOCUSED_TASK + std::to_string(missionId));
543          eventHandler_->PostTask(feedfunc);
544      } else {
545          HILOGE("eventHandler_ is nullptr");
546          return ERR_NULL_OBJECT;
547      }
548      HILOGI("SetMissionContinueState end");
549      return ERR_OK;
550  }
551  
DealSetMissionContinueStateBusiness(const int32_t missionId,const AAFwk::ContinueState & state)552  int32_t DMSContinueSendMgr::DealSetMissionContinueStateBusiness(const int32_t missionId,
553      const AAFwk::ContinueState &state)
554  {
555      HILOGI("DealSetMissionContinueStateBusiness start, missionId: %{public}d, state: %{public}d", missionId, state);
556      if (info_.currentMissionId != missionId) {
557          HILOGE("mission is not focused, broadcast task abort, missionId: %{public}d", missionId);
558          return INVALID_PARAMETERS_ERR;
559      }
560      std::string bundleName;
561      if (state == AAFwk::ContinueState::CONTINUESTATE_ACTIVE &&
562          GetBundleNameByMissionId(missionId, bundleName) != ERR_OK) {
563          HILOGE("mission is not focused, broadcast task abort, missionId: %{public}d", missionId);
564          return INVALID_PARAMETERS_ERR;
565      }
566      if (!info_.currentIsContinuable) {
567          HILOGI("mission is not continuable, broadcast task abort, missionId: %{public}d", missionId);
568          return INVALID_PARAMETERS_ERR;
569      }
570  
571      uint16_t bundleNameId = 0;
572      uint8_t continueTypeId = 0;
573      int32_t ret = GetBundleNameIdAndContinueTypeId(missionId, state, bundleNameId, continueTypeId);
574      if (ret != ERR_OK) {
575          HILOGE("Get focused contineTypeId failed, contineTypeId: %{public}u, ret: %{public}d", continueTypeId, ret);
576          return ret;
577      }
578  
579      ret = SetStateSendEvent(bundleNameId, continueTypeId, state);
580      if (ret != ERR_OK) {
581          HILOGE("SetStateSendEvent failed");
582          return ret;
583      }
584      HILOGI("DealSetMissionContinueStateBusiness end. ContinueState set to: %{public}d", state);
585      return ERR_OK;
586  }
587  
GetBundleNameIdAndContinueTypeId(const int32_t missionId,const AAFwk::ContinueState & state,uint16_t & bundleNameId,uint8_t & continueTypeId)588  int32_t DMSContinueSendMgr::GetBundleNameIdAndContinueTypeId(const int32_t missionId, const AAFwk::ContinueState& state,
589      uint16_t& bundleNameId, uint8_t& continueTypeId)
590  {
591      std::string bundleName;
592      int32_t ret = GetBundleNameByMissionId(missionId, bundleName);
593      if (ret != ERR_OK) {
594          HILOGW("get iterItem failed from focusedMission, try screenOffHandler");
595          if (GetBundleNameByScreenOffInfo(missionId, bundleName) != ERR_OK) {
596              HILOGE("get bundleName failed, missionId: %{public}d, ret: %{public}d", missionId, ret);
597              return ret;
598          }
599      }
600      HILOGI("get bundleName success, missionId: %{public}d, bundleName: %{public}s", missionId, bundleName.c_str());
601      if (!CheckBundleContinueConfig(bundleName)) {
602          HILOGI("App does not allow continue in config file, bundle name %{public}s, missionId: %{public}d",
603              bundleName.c_str(), missionId);
604          return REMOTE_DEVICE_BIND_ABILITY_ERR;
605      }
606  
607      ret = BundleManagerInternal::GetBundleNameId(bundleName, bundleNameId);
608      if (ret != ERR_OK) {
609          HILOGE("get bundleNameId failed, bundleNameId: %{public}u, ret: %{public}d", bundleNameId, ret);
610          return ret;
611      }
612  
613      std::string abilityName;
614      ret = GetAbilityNameByMissionId(missionId, abilityName);
615      if (ret != ERR_OK) {
616          HILOGE("get abilityName failed, broadcast task abort, missionId: %{public}d, ret: %{public}d",
617              missionId, ret);
618          return ret;
619      }
620  
621      return BundleManagerInternal::GetContinueTypeId(bundleName, abilityName, continueTypeId);
622  }
623  
OnMMIEvent()624  void DMSContinueSendMgr::OnMMIEvent()
625  {
626      DMSContinueSendMgr::GetInstance().NotifyMissionFocused(INVALID_MISSION_ID, FocusedReason::MMI);
627  }
628  
NotifyDeviceOnline()629  int32_t DMSContinueSendMgr::NotifyDeviceOnline()
630  {
631      HILOGD("NotifyDeviceOnline called");
632      if (GetCurrentMissionId() <= 0) {
633          return INVALID_MISSION_ID;
634      }
635      NotifyMissionFocused(info_.currentMissionId, FocusedReason::ONLINE);
636      return ERR_OK;
637  }
638  
OnDeviceScreenOff()639  void DMSContinueSendMgr::OnDeviceScreenOff()
640  {
641      HILOGI("OnDeviceScreenOff called");
642      int32_t missionId = info_.currentMissionId;
643      if (!info_.currentIsContinuable || CheckContinueState(missionId) != ERR_OK) {
644          HILOGW("current mission is not continuable, ignore");
645          return;
646      }
647      auto feedfunc = [this, missionId]() {
648          if (screenOffHandler_ != nullptr) {
649              screenOffHandler_->OnDeviceScreenOff(missionId);
650          }
651      };
652      if (eventHandler_ == nullptr) {
653          HILOGE("eventHandler_ is nullptr");
654          return;
655      }
656      eventHandler_->PostTask(feedfunc);
657  }
658  
OnDeviceScreenOn()659  void DMSContinueSendMgr::OnDeviceScreenOn()
660  {
661      HILOGI("OnDeviceScreenOn called");
662      auto feedfunc = [this]() {
663          if (screenOffHandler_ != nullptr) {
664              screenOffHandler_->OnDeviceScreenOn();
665          }
666      };
667      if (eventHandler_ == nullptr) {
668          HILOGE("eventHandler_ is nullptr");
669          return;
670      }
671      eventHandler_->PostTask(feedfunc);
672  }
673  
GetMissionId()674  int32_t DMSContinueSendMgr::ScreenOffHandler::GetMissionId()
675  {
676      return unfoInfo_.missionId;
677  }
678  
GetBundleName()679  std::string DMSContinueSendMgr::ScreenOffHandler::GetBundleName()
680  {
681      return unfoInfo_.bundleName;
682  }
683  
GetAbilityName()684  std::string DMSContinueSendMgr::ScreenOffHandler::GetAbilityName()
685  {
686      return unfoInfo_.abilityName;
687  }
688  
GetAccessTokenId()689  uint32_t DMSContinueSendMgr::ScreenOffHandler::GetAccessTokenId()
690  {
691      return unfoInfo_.accessToken;
692  }
693  
IsDeviceScreenOn()694  bool DMSContinueSendMgr::ScreenOffHandler::IsDeviceScreenOn()
695  {
696      return isScreenOn_;
697  }
698  
699  
OnDeviceScreenOff(int32_t missionId)700  void DMSContinueSendMgr::ScreenOffHandler::OnDeviceScreenOff(int32_t missionId)
701  {
702      HILOGI("ScreenOffHandler::OnDeviceScreenOff called");
703      isScreenOn_ = false;
704      if (unfoInfo_.missionId != INVALID_MISSION_ID && (GetTickCount()- unfoInfo_.unfoTime) < TIME_DELAYED) {
705          // handle unfocus before screen off
706          DMSContinueSendMgr::GetInstance().SendScreenOffEvent(DMS_FOCUSED_TYPE);
707      }
708      DMSContinueSendMgr::GetInstance().PostUnfocusedTaskWithDelay(missionId, UnfocusedReason::SCREENOFF);
709  }
710  
OnDeviceScreenOn()711  void DMSContinueSendMgr::ScreenOffHandler::OnDeviceScreenOn()
712  {
713      HILOGI("ScreenOffHandler::OnDeviceScreenOn called");
714      isScreenOn_ = true;
715  }
716  
ClearScreenOffInfo()717  void DMSContinueSendMgr::ScreenOffHandler::ClearScreenOffInfo()
718  {
719      HILOGI("clear last unfocused info");
720      unfoInfo_.missionId = INVALID_MISSION_ID;
721      unfoInfo_.unfoTime = 0;
722      unfoInfo_.bundleName = "";
723      unfoInfo_.accessToken = 0;
724      unfoInfo_.abilityName = "";
725  }
726  
SetScreenOffInfo(int32_t missionId,std::string bundleName,uint16_t bundleNameId,std::string abilityName)727  void DMSContinueSendMgr::ScreenOffHandler::SetScreenOffInfo(int32_t missionId, std::string bundleName,
728      uint16_t bundleNameId, std::string abilityName)
729  {
730      HILOGI("set last unfocused info, missionId: %{public}d, bundleName: %{public}s, bundleNameId: %{public}u",
731          missionId, bundleName.c_str(), bundleNameId);
732      unfoInfo_.missionId = missionId;
733      unfoInfo_.unfoTime = GetTickCount();
734      unfoInfo_.bundleName = bundleName;
735      unfoInfo_.accessToken = bundleNameId;
736      unfoInfo_.abilityName = abilityName;
737  }
738  
GetAccessTokenIdSendEvent(std::string bundleName,UnfocusedReason reason,uint16_t & bundleNameId,uint8_t & continueTypeId)739  int32_t DMSContinueSendMgr::GetAccessTokenIdSendEvent(std::string bundleName,
740      UnfocusedReason reason, uint16_t& bundleNameId, uint8_t& continueTypeId)
741  {
742      int32_t ret = BundleManagerInternal::GetBundleNameId(bundleName, bundleNameId);
743      if (ret != ERR_OK) {
744          HILOGE("Get unfocused bundleNameId failed, bundleNameId: %{public}u, ret: %{public}d", bundleNameId, ret);
745          return ret;
746      }
747  
748      if (screenOffHandler_ != nullptr && screenOffHandler_->IsDeviceScreenOn()) {
749          ret = SendSoftbusEvent(bundleNameId, continueTypeId, DMS_UNFOCUSED_TYPE);
750          if (ret != ERR_OK) {
751              HILOGE("SendSoftbusEvent unfocused failed, ret: %{public}d", ret);
752              return ret;
753          }
754      }
755      return ret;
756  }
757  
SetStateSendEvent(const uint16_t bundleNameId,const uint8_t & continueTypeId,const AAFwk::ContinueState & state)758  int32_t DMSContinueSendMgr::SetStateSendEvent(const uint16_t bundleNameId, const uint8_t& continueTypeId,
759      const AAFwk::ContinueState &state)
760  {
761      if (state == AAFwk::ContinueState::CONTINUESTATE_INACTIVE) {
762          RemoveMMIListener();
763      } else {
764          AddMMIListener();
765      }
766  
767      if (!DataShareManager::GetInstance().IsCurrentContinueSwitchOn()) {
768          HILOGE("ContinueSwitch status is off");
769          return DMS_PERMISSION_DENIED;
770      }
771  
772      uint8_t type = state == AAFwk::ContinueState::CONTINUESTATE_INACTIVE ? DMS_UNFOCUSED_TYPE : DMS_FOCUSED_TYPE;
773      int32_t ret = SendSoftbusEvent(bundleNameId, continueTypeId, type);
774      if (ret != ERR_OK) {
775          HILOGE("SendSoftbusEvent setContinueState failed, ret: %{public}d", ret);
776          return ret;
777      }
778      return ret;
779  }
780  
DeleteContinueLaunchMissionInfo(const int32_t missionId)781  void DMSContinueSendMgr::DeleteContinueLaunchMissionInfo(const int32_t missionId)
782  {
783      HILOGD("called");
784      std::lock_guard<std::mutex> continueLaunchMissionMapLock(eventMutex_);
785      if (continueLaunchMission_.empty()) {
786          return;
787      }
788      for (auto iter = continueLaunchMission_.begin(); iter != continueLaunchMission_.end(); iter++) {
789          if (iter->second == missionId) {
790              continueLaunchMission_.erase(iter);
791              return;
792          }
793      }
794  }
795  
GetContinueLaunchMissionInfo(const int32_t missionId,ContinueLaunchMissionInfo & missionInfo)796  int32_t DMSContinueSendMgr::GetContinueLaunchMissionInfo(const int32_t missionId,
797      ContinueLaunchMissionInfo& missionInfo)
798  {
799      HILOGD("start, missionId: %{public}d", missionId);
800      std::lock_guard<std::mutex> continueLaunchMissionMapLock(eventMutex_);
801      for (auto iter = continueLaunchMission_.begin(); iter != continueLaunchMission_.end(); iter++) {
802          if (iter->second == missionId) {
803              missionInfo = iter->first;
804              HILOGI("get missionInfo end, missionId: %{public}d", missionId);
805              return ERR_OK;
806          }
807      }
808      HILOGW("get missionInfo failed from continueLaunchMission");
809      return INVALID_PARAMETERS_ERR;
810  }
811  
UpdateContinueLaunchMission(const AAFwk::MissionInfo & info)812  bool DMSContinueSendMgr::UpdateContinueLaunchMission(const AAFwk::MissionInfo& info)
813  {
814      auto flag = info.want.GetFlags();
815      if ((flag & AAFwk::Want::FLAG_ABILITY_CONTINUATION) != AAFwk::Want::FLAG_ABILITY_CONTINUATION &&
816          (flag & AAFwk::Want::FLAG_ABILITY_PREPARE_CONTINUATION) != AAFwk::Want::FLAG_ABILITY_PREPARE_CONTINUATION) {
817          return false;
818      }
819  
820      std::string bundleName = info.want.GetBundle();
821      std::string abilityName = info.want.GetElement().GetAbilityName();
822      ContinueLaunchMissionInfo continueLaunchMissionInfo = { bundleName, abilityName };
823  
824      std::lock_guard<std::mutex> continueLaunchMissionMapLock(eventMutex_);
825      auto iterItem = continueLaunchMission_.find(continueLaunchMissionInfo);
826      if (iterItem == continueLaunchMission_.end()) {
827          HILOGI("not find continueLaunchMissionInfo");
828          continueLaunchMission_[continueLaunchMissionInfo] = info.id;
829          return true;
830      }
831      if (iterItem->second < info.id) {
832          HILOGI("old missionId: %{public}d, new missionId: %{public}d", iterItem->second, info.id);
833          continueLaunchMission_[continueLaunchMissionInfo] = info.id;
834          return true;
835      }
836      return false;
837  }
838  } // namespace DistributedSchedule
839  } // namespace OHOS
840