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 25namespace OHOS::Ace::ComponentTest { 26 27constexpr uint32_t period = 2000 / 4; 28constexpr uint32_t delay_next_check = 1000 / 4; 29constexpr uint32_t delay_double_confirm = 2000 / 4; 30constexpr uint32_t delay_after_change = 5000 / 4; 31 32constexpr uint8_t max_idle_check_retry = 10; 33 34void UpdatePipelineStatus() 35{ 36 ComponentTestManagerImpl::Get()->pipelineStatusHolder.Update(); 37} 38 39void 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 53void 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 64RefPtr<IdleMonitorThread> IdleMonitorThread::Create() 65{ 66 auto idleMonitorThread = MakeRefPtr<IdleMonitorThread>(); 67 idleMonitorThread->thread = TaskRunnerAdapterFactory::Create(false, "IdleMonitorThread"); 68 return idleMonitorThread; 69} 70 71void IdleMonitorThread::Stop() 72{ 73 thread.Reset(); 74} 75 76void IdleMonitorThread::SetIdleNotifycallback(IdleNotifycallback callback) 77{ 78 callback_ = callback; 79} 80 81void IdleMonitorThread::SetTaskExecutor(RefPtr<TaskExecutor> taskExecutor) 82{ 83 taskExecutor_ = taskExecutor; 84} 85 86void IdleMonitorThread::PostInitializeTask() 87{ 88 thread->PostDelayedTask([this]() { PostCheckTask([this]() { VsyncCountFirstCheck(); }, period); }, period, {}); 89} 90 91void IdleMonitorThread::PostCheckTask(std::function<void()>&& task, uint32_t delay) 92{ 93 thread->PostDelayedTask(std::move(task), delay, {}); 94} 95 96IdleWatcher::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 105void IdleWatcher::Destroy() 106{ 107 idleMonitorThread_->Stop(); 108 std::lock_guard<std::mutex> lock(observersMutex_); 109 pendingIdleObservers_.clear(); 110} 111 112void 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 132void 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 149void IdleWatcher::RequestContinuousIdleStatusNotification(IdleNotifycallback&& continuousIdleCallback) 150{ 151 continuousIdleCallback_ = std::move(continuousIdleCallback); 152} 153 154void IdleWatcher::ClaimLongOperation() 155{ 156 ComponentTestManagerImpl::Get()->pipelineStatusHolder.IncreaseLongOpt(); 157} 158 159void IdleWatcher::LongOperationComplete() 160{ 161 ComponentTestManagerImpl::Get()->pipelineStatusHolder.DecreaseLongOpt(); 162} 163} // namespace OHOS::Ace::ComponentTest 164