1 /*
2 * Copyright (C) 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 "component_test/idle_watcher.h"
17
18 #include "component_test/component_test_manager_impl.h"
19
20 #include "base/log/log.h"
21 #include "base/thread/task_executor.h"
22 #include "core/common/task_runner_adapter.h"
23 #include "core/common/task_runner_adapter_factory.h"
24
25 namespace OHOS::Ace::ComponentTest {
26
27 constexpr uint32_t period = 2000 / 4;
28 constexpr uint32_t delay_next_check = 1000 / 4;
29 constexpr uint32_t delay_double_confirm = 2000 / 4;
30 constexpr uint32_t delay_after_change = 5000 / 4;
31
32 constexpr uint8_t max_idle_check_retry = 10;
33
UpdatePipelineStatus()34 void UpdatePipelineStatus()
35 {
36 ComponentTestManagerImpl::Get()->pipelineStatusHolder.Update();
37 }
38
VsyncCountFirstCheck()39 void IdleMonitorThread::VsyncCountFirstCheck()
40 {
41 if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.Check()) {
42 PostCheckTask([this]() { VsyncCountSecondCheck(); }, delay_double_confirm);
43 } else {
44 if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterReached(max_idle_check_retry)) {
45 LOGI("IdleMonitorThread wait pipeline idle timeout");
46 ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterClear();
47 callback_();
48 }
49 PostCheckTask([this]() { VsyncCountFirstCheck(); }, delay_next_check);
50 }
51 }
52
VsyncCountSecondCheck()53 void IdleMonitorThread::VsyncCountSecondCheck()
54 {
55 if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.Check()) {
56 ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterClear();
57 callback_();
58 IdleMonitorThread::PostCheckTask([this]() { VsyncCountFirstCheck(); }, period);
59 } else {
60 IdleMonitorThread::PostCheckTask([this]() { VsyncCountFirstCheck(); }, delay_after_change);
61 }
62 }
63
Create()64 RefPtr<IdleMonitorThread> IdleMonitorThread::Create()
65 {
66 auto idleMonitorThread = MakeRefPtr<IdleMonitorThread>();
67 idleMonitorThread->thread = TaskRunnerAdapterFactory::Create(false, "IdleMonitorThread");
68 return idleMonitorThread;
69 }
70
Stop()71 void IdleMonitorThread::Stop()
72 {
73 thread.Reset();
74 }
75
SetIdleNotifycallback(IdleNotifycallback callback)76 void IdleMonitorThread::SetIdleNotifycallback(IdleNotifycallback callback)
77 {
78 callback_ = callback;
79 }
80
SetTaskExecutor(RefPtr<TaskExecutor> taskExecutor)81 void IdleMonitorThread::SetTaskExecutor(RefPtr<TaskExecutor> taskExecutor)
82 {
83 taskExecutor_ = taskExecutor;
84 }
85
PostInitializeTask()86 void IdleMonitorThread::PostInitializeTask()
87 {
88 thread->PostDelayedTask([this]() { PostCheckTask([this]() { VsyncCountFirstCheck(); }, period); }, period, {});
89 }
90
PostCheckTask(std::function<void()>&& task, uint32_t delay)91 void IdleMonitorThread::PostCheckTask(std::function<void()>&& task, uint32_t delay)
92 {
93 thread->PostDelayedTask(std::move(task), delay, {});
94 }
95
IdleWatcher(RefPtr<TaskExecutor> taskExecutor)96 IdleWatcher::IdleWatcher(RefPtr<TaskExecutor> taskExecutor)
97 {
98 keepingIdle_ = false;
99 idleMonitorThread_ = IdleMonitorThread::Create();
100 idleMonitorThread_->SetIdleNotifycallback([this] { TriggerIdleNotification(); });
101 idleMonitorThread_->SetTaskExecutor(taskExecutor);
102 idleMonitorThread_->PostInitializeTask();
103 }
104
Destroy()105 void IdleWatcher::Destroy()
106 {
107 idleMonitorThread_->Stop();
108 std::lock_guard<std::mutex> lock(observersMutex_);
109 pendingIdleObservers_.clear();
110 }
111
TriggerIdleNotification()112 void IdleWatcher::TriggerIdleNotification()
113 {
114 LOGI("Triggering idle notification");
115 keepingIdle_ = true;
116 if (pendingIdleObservers_.empty()) {
117 ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterAdd();
118 if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterReached(CONTINUOUS_IDLE_TIME) &&
119 continuousIdleCallback_) {
120 continuousIdleCallback_();
121 continuousIdleCallback_ = nullptr;
122 }
123 } else {
124 std::lock_guard<std::mutex> lock(observersMutex_);
125 for (IdleNotifycallback& notifycallback : pendingIdleObservers_) {
126 notifycallback();
127 }
128 pendingIdleObservers_.clear();
129 }
130 }
131
RequestNextIdleStatusNotification(IdleNotifycallback&& notifycallback, bool haveUIChange)132 void IdleWatcher::RequestNextIdleStatusNotification(IdleNotifycallback&& notifycallback, bool haveUIChange)
133 {
134 ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterClear();
135 if (haveUIChange) {
136 notifycallback = [this, notifycallback]() {
137 keepingIdle_ = false;
138 notifycallback();
139 };
140 }
141 if (keepingIdle_) {
142 notifycallback();
143 } else {
144 std::lock_guard<std::mutex> lock(observersMutex_);
145 pendingIdleObservers_.emplace_back(notifycallback);
146 }
147 }
148
RequestContinuousIdleStatusNotification(IdleNotifycallback&& continuousIdleCallback)149 void IdleWatcher::RequestContinuousIdleStatusNotification(IdleNotifycallback&& continuousIdleCallback)
150 {
151 continuousIdleCallback_ = std::move(continuousIdleCallback);
152 }
153
ClaimLongOperation()154 void IdleWatcher::ClaimLongOperation()
155 {
156 ComponentTestManagerImpl::Get()->pipelineStatusHolder.IncreaseLongOpt();
157 }
158
LongOperationComplete()159 void IdleWatcher::LongOperationComplete()
160 {
161 ComponentTestManagerImpl::Get()->pipelineStatusHolder.DecreaseLongOpt();
162 }
163 } // namespace OHOS::Ace::ComponentTest
164