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