1 /*
2 * Copyright (c) 2024-2025 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 #include "conditions/screen_listener.h"
16
17 #include <string>
18 #include <cinttypes>
19
20 #include "common_event_manager.h"
21 #include "common_event_support.h"
22 #include "matching_skills.h"
23 #include "want.h"
24 #include "work_sched_hilog.h"
25 #include "work_sched_utils.h"
26 #include "work_status.h"
27 #include "work_event_handler.h"
28 #include "work_scheduler_service.h"
29 #include "work_sched_constants.h"
30 #include "conditions/timer_info.h"
31 #include "work_sched_hisysevent_report.h"
32 #include "work_sched_data_manager.h"
33
34 namespace OHOS {
35 namespace WorkScheduler {
ScreenEventSubscriber(const EventFwk::CommonEventSubscribeInfo & subscribeInfo,ScreenListener & listener)36 ScreenEventSubscriber::ScreenEventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo,
37 ScreenListener &listener) : EventFwk::CommonEventSubscriber(subscribeInfo), listener_(listener) {}
38
OnReceiveEvent(const EventFwk::CommonEventData & data)39 void ScreenEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data)
40 {
41 const std::string action = data.GetWant().GetAction();
42 WS_HILOGI("OnReceiveEvent get action: %{public}s", action.c_str());
43 auto eventHandler = listener_.service_->GetHandler();
44 if (!eventHandler) {
45 WS_HILOGE("event handler is null");
46 return;
47 }
48 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED) {
49 if (DelayedSingleton<DataManager>::GetInstance()->GetDeepIdle()) {
50 DelayedSingleton<DataManager>::GetInstance()->SetDeepIdle(false);
51 WorkSchedUtil::HiSysEventStateChanged({"DEEP_IDLE", 0});
52 }
53 listener_.StopTimer();
54 listener_.OnConditionChanged(WorkCondition::Type::DEEP_IDLE,
55 std::make_shared<DetectorValue>(0, 0, false, std::string()));
56 auto task = [weak = weak_from_this()]() {
57 auto strong = weak.lock();
58 if (!strong) {
59 WS_HILOGE("ScreenEventSubscriber::OnReceiveEvent strong is null");
60 return;
61 }
62 int32_t ret = strong->listener_.service_->StopDeepIdleWorks();
63 if (ret != ERR_OK) {
64 WS_HILOGE("stop work after unlocking failed, error code:%{public}d.", ret);
65 } else {
66 WS_HILOGI("stop work after unlocking successed.");
67 }
68 };
69 eventHandler->PostTask(task);
70 } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
71 if (listener_.timerId_ != 0) {
72 WS_HILOGW("has send check deep idle msg, ignore");
73 return;
74 }
75 listener_.StartTimer();
76 }
77 }
78
ScreenListener(std::shared_ptr<WorkQueueManager> workQueueManager,std::shared_ptr<WorkSchedulerService> service)79 ScreenListener::ScreenListener(std::shared_ptr<WorkQueueManager> workQueueManager,
80 std::shared_ptr<WorkSchedulerService> service)
81 {
82 workQueueManager_ = workQueueManager;
83 service_ = service;
84 }
85
~ScreenListener()86 ScreenListener::~ScreenListener()
87 {
88 this->Stop();
89 }
90
CreateScreenEventSubscriber(ScreenListener & listener)91 std::shared_ptr<EventFwk::CommonEventSubscriber> CreateScreenEventSubscriber(ScreenListener &listener)
92 {
93 EventFwk::MatchingSkills skill = EventFwk::MatchingSkills();
94 skill.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED);
95 skill.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF);
96 EventFwk::CommonEventSubscribeInfo info(skill);
97 return std::make_shared<ScreenEventSubscriber>(info, listener);
98 }
99
Start()100 bool ScreenListener::Start()
101 {
102 WS_HILOGD("screen listener start.");
103 this->commonEventSubscriber = CreateScreenEventSubscriber(*this);
104 return EventFwk::CommonEventManager::SubscribeCommonEvent(this->commonEventSubscriber);
105 }
106
Stop()107 bool ScreenListener::Stop()
108 {
109 WS_HILOGD("screen listener stop.");
110 if (this->commonEventSubscriber != nullptr) {
111 bool result = EventFwk::CommonEventManager::UnSubscribeCommonEvent(this->commonEventSubscriber);
112 if (result) {
113 this->commonEventSubscriber = nullptr;
114 }
115 return result;
116 }
117 return true;
118 }
119
OnConditionChanged(WorkCondition::Type conditionType,std::shared_ptr<DetectorValue> conditionVal)120 void ScreenListener::OnConditionChanged(WorkCondition::Type conditionType,
121 std::shared_ptr<DetectorValue> conditionVal)
122 {
123 if (workQueueManager_ != nullptr) {
124 workQueueManager_->OnConditionChanged(conditionType, conditionVal);
125 } else {
126 WS_HILOGE("workQueueManager_ is nullptr.");
127 }
128 }
129
StartTimer()130 void ScreenListener::StartTimer()
131 {
132 WS_HILOGI("deep idle timer start with time = %{public}d.", MIN_DEEP_IDLE_SCREEN_OFF_TIME_MIN);
133 auto task = [=]() {
134 WS_HILOGI("Into deep idle mode");
135 DelayedSingleton<DataManager>::GetInstance()->SetDeepIdle(true);
136 service_->HandleDeepIdleMsg();
137 };
138 auto timerInfo = std::make_shared<TimerInfo>();
139 uint8_t type = static_cast<uint8_t>(timerInfo->TIMER_TYPE_EXACT) |
140 static_cast<uint8_t>(timerInfo->TIMER_TYPE_REALTIME);
141 timerInfo->SetType(static_cast<int>(type));
142 timerInfo->SetRepeat(false);
143 timerInfo->SetInterval(MIN_DEEP_IDLE_SCREEN_OFF_TIME_MIN);
144 timerInfo->SetCallbackInfo(task);
145 timerId_ = TimeServiceClient::GetInstance()->CreateTimer(timerInfo);
146 if (timerId_ == 0) {
147 WS_HILOGE("TimerListener CreateTimer failed");
148 return;
149 }
150 bool res = TimeServiceClient::GetInstance()->StartTimer(timerId_,
151 TimeServiceClient::GetInstance()->GetBootTimeMs() + MIN_DEEP_IDLE_SCREEN_OFF_TIME_MIN);
152 WS_HILOGI("deep idle timer start, res is %{public}d, timerId %{public}" PRIu64, res, timerId_);
153 }
154
StopTimer()155 void ScreenListener::StopTimer()
156 {
157 if (timerId_ > 0) {
158 MiscServices::TimeServiceClient::GetInstance()->StopTimer(timerId_);
159 MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(timerId_);
160 timerId_ = 0;
161 WS_HILOGI("deep idle timer stop success");
162 }
163 WS_HILOGI("deep idle timer stop end");
164 }
165 } // namespace WorkScheduler
166 } // namespace OHOS