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