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