123b3eb3cSopenharmony_ci/*
223b3eb3cSopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd.
323b3eb3cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
423b3eb3cSopenharmony_ci * you may not use this file except in compliance with the License.
523b3eb3cSopenharmony_ci * You may obtain a copy of the License at
623b3eb3cSopenharmony_ci *
723b3eb3cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
823b3eb3cSopenharmony_ci *
923b3eb3cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1023b3eb3cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1123b3eb3cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1223b3eb3cSopenharmony_ci * See the License for the specific language governing permissions and
1323b3eb3cSopenharmony_ci * limitations under the License.
1423b3eb3cSopenharmony_ci */
1523b3eb3cSopenharmony_ci
1623b3eb3cSopenharmony_ci#include "component_test/idle_watcher.h"
1723b3eb3cSopenharmony_ci
1823b3eb3cSopenharmony_ci#include "component_test/component_test_manager_impl.h"
1923b3eb3cSopenharmony_ci
2023b3eb3cSopenharmony_ci#include "base/log/log.h"
2123b3eb3cSopenharmony_ci#include "base/thread/task_executor.h"
2223b3eb3cSopenharmony_ci#include "core/common/task_runner_adapter.h"
2323b3eb3cSopenharmony_ci#include "core/common/task_runner_adapter_factory.h"
2423b3eb3cSopenharmony_ci
2523b3eb3cSopenharmony_cinamespace OHOS::Ace::ComponentTest {
2623b3eb3cSopenharmony_ci
2723b3eb3cSopenharmony_ciconstexpr uint32_t period = 2000 / 4;
2823b3eb3cSopenharmony_ciconstexpr uint32_t delay_next_check = 1000 / 4;
2923b3eb3cSopenharmony_ciconstexpr uint32_t delay_double_confirm = 2000 / 4;
3023b3eb3cSopenharmony_ciconstexpr uint32_t delay_after_change = 5000 / 4;
3123b3eb3cSopenharmony_ci
3223b3eb3cSopenharmony_ciconstexpr uint8_t max_idle_check_retry = 10;
3323b3eb3cSopenharmony_ci
3423b3eb3cSopenharmony_civoid UpdatePipelineStatus()
3523b3eb3cSopenharmony_ci{
3623b3eb3cSopenharmony_ci    ComponentTestManagerImpl::Get()->pipelineStatusHolder.Update();
3723b3eb3cSopenharmony_ci}
3823b3eb3cSopenharmony_ci
3923b3eb3cSopenharmony_civoid IdleMonitorThread::VsyncCountFirstCheck()
4023b3eb3cSopenharmony_ci{
4123b3eb3cSopenharmony_ci    if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.Check()) {
4223b3eb3cSopenharmony_ci        PostCheckTask([this]() { VsyncCountSecondCheck(); }, delay_double_confirm);
4323b3eb3cSopenharmony_ci    } else {
4423b3eb3cSopenharmony_ci        if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterReached(max_idle_check_retry)) {
4523b3eb3cSopenharmony_ci            LOGI("IdleMonitorThread wait pipeline idle timeout");
4623b3eb3cSopenharmony_ci            ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterClear();
4723b3eb3cSopenharmony_ci            callback_();
4823b3eb3cSopenharmony_ci        }
4923b3eb3cSopenharmony_ci        PostCheckTask([this]() { VsyncCountFirstCheck(); }, delay_next_check);
5023b3eb3cSopenharmony_ci    }
5123b3eb3cSopenharmony_ci}
5223b3eb3cSopenharmony_ci
5323b3eb3cSopenharmony_civoid IdleMonitorThread::VsyncCountSecondCheck()
5423b3eb3cSopenharmony_ci{
5523b3eb3cSopenharmony_ci    if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.Check()) {
5623b3eb3cSopenharmony_ci        ComponentTestManagerImpl::Get()->pipelineStatusHolder.RetryCounterClear();
5723b3eb3cSopenharmony_ci        callback_();
5823b3eb3cSopenharmony_ci        IdleMonitorThread::PostCheckTask([this]() { VsyncCountFirstCheck(); }, period);
5923b3eb3cSopenharmony_ci    } else {
6023b3eb3cSopenharmony_ci        IdleMonitorThread::PostCheckTask([this]() { VsyncCountFirstCheck(); }, delay_after_change);
6123b3eb3cSopenharmony_ci    }
6223b3eb3cSopenharmony_ci}
6323b3eb3cSopenharmony_ci
6423b3eb3cSopenharmony_ciRefPtr<IdleMonitorThread> IdleMonitorThread::Create()
6523b3eb3cSopenharmony_ci{
6623b3eb3cSopenharmony_ci    auto idleMonitorThread = MakeRefPtr<IdleMonitorThread>();
6723b3eb3cSopenharmony_ci    idleMonitorThread->thread = TaskRunnerAdapterFactory::Create(false, "IdleMonitorThread");
6823b3eb3cSopenharmony_ci    return idleMonitorThread;
6923b3eb3cSopenharmony_ci}
7023b3eb3cSopenharmony_ci
7123b3eb3cSopenharmony_civoid IdleMonitorThread::Stop()
7223b3eb3cSopenharmony_ci{
7323b3eb3cSopenharmony_ci    thread.Reset();
7423b3eb3cSopenharmony_ci}
7523b3eb3cSopenharmony_ci
7623b3eb3cSopenharmony_civoid IdleMonitorThread::SetIdleNotifycallback(IdleNotifycallback callback)
7723b3eb3cSopenharmony_ci{
7823b3eb3cSopenharmony_ci    callback_ = callback;
7923b3eb3cSopenharmony_ci}
8023b3eb3cSopenharmony_ci
8123b3eb3cSopenharmony_civoid IdleMonitorThread::SetTaskExecutor(RefPtr<TaskExecutor> taskExecutor)
8223b3eb3cSopenharmony_ci{
8323b3eb3cSopenharmony_ci    taskExecutor_ = taskExecutor;
8423b3eb3cSopenharmony_ci}
8523b3eb3cSopenharmony_ci
8623b3eb3cSopenharmony_civoid IdleMonitorThread::PostInitializeTask()
8723b3eb3cSopenharmony_ci{
8823b3eb3cSopenharmony_ci    thread->PostDelayedTask([this]() { PostCheckTask([this]() { VsyncCountFirstCheck(); }, period); }, period, {});
8923b3eb3cSopenharmony_ci}
9023b3eb3cSopenharmony_ci
9123b3eb3cSopenharmony_civoid IdleMonitorThread::PostCheckTask(std::function<void()>&& task, uint32_t delay)
9223b3eb3cSopenharmony_ci{
9323b3eb3cSopenharmony_ci    thread->PostDelayedTask(std::move(task), delay, {});
9423b3eb3cSopenharmony_ci}
9523b3eb3cSopenharmony_ci
9623b3eb3cSopenharmony_ciIdleWatcher::IdleWatcher(RefPtr<TaskExecutor> taskExecutor)
9723b3eb3cSopenharmony_ci{
9823b3eb3cSopenharmony_ci    keepingIdle_ = false;
9923b3eb3cSopenharmony_ci    idleMonitorThread_ = IdleMonitorThread::Create();
10023b3eb3cSopenharmony_ci    idleMonitorThread_->SetIdleNotifycallback([this] { TriggerIdleNotification(); });
10123b3eb3cSopenharmony_ci    idleMonitorThread_->SetTaskExecutor(taskExecutor);
10223b3eb3cSopenharmony_ci    idleMonitorThread_->PostInitializeTask();
10323b3eb3cSopenharmony_ci}
10423b3eb3cSopenharmony_ci
10523b3eb3cSopenharmony_civoid IdleWatcher::Destroy()
10623b3eb3cSopenharmony_ci{
10723b3eb3cSopenharmony_ci    idleMonitorThread_->Stop();
10823b3eb3cSopenharmony_ci    std::lock_guard<std::mutex> lock(observersMutex_);
10923b3eb3cSopenharmony_ci    pendingIdleObservers_.clear();
11023b3eb3cSopenharmony_ci}
11123b3eb3cSopenharmony_ci
11223b3eb3cSopenharmony_civoid IdleWatcher::TriggerIdleNotification()
11323b3eb3cSopenharmony_ci{
11423b3eb3cSopenharmony_ci    LOGI("Triggering idle notification");
11523b3eb3cSopenharmony_ci    keepingIdle_ = true;
11623b3eb3cSopenharmony_ci    if (pendingIdleObservers_.empty()) {
11723b3eb3cSopenharmony_ci        ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterAdd();
11823b3eb3cSopenharmony_ci        if (ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterReached(CONTINUOUS_IDLE_TIME) &&
11923b3eb3cSopenharmony_ci            continuousIdleCallback_) {
12023b3eb3cSopenharmony_ci            continuousIdleCallback_();
12123b3eb3cSopenharmony_ci            continuousIdleCallback_ = nullptr;
12223b3eb3cSopenharmony_ci        }
12323b3eb3cSopenharmony_ci    } else {
12423b3eb3cSopenharmony_ci        std::lock_guard<std::mutex> lock(observersMutex_);
12523b3eb3cSopenharmony_ci        for (IdleNotifycallback& notifycallback : pendingIdleObservers_) {
12623b3eb3cSopenharmony_ci            notifycallback();
12723b3eb3cSopenharmony_ci        }
12823b3eb3cSopenharmony_ci        pendingIdleObservers_.clear();
12923b3eb3cSopenharmony_ci    }
13023b3eb3cSopenharmony_ci}
13123b3eb3cSopenharmony_ci
13223b3eb3cSopenharmony_civoid IdleWatcher::RequestNextIdleStatusNotification(IdleNotifycallback&& notifycallback, bool haveUIChange)
13323b3eb3cSopenharmony_ci{
13423b3eb3cSopenharmony_ci    ComponentTestManagerImpl::Get()->pipelineStatusHolder.IdleCounterClear();
13523b3eb3cSopenharmony_ci    if (haveUIChange) {
13623b3eb3cSopenharmony_ci        notifycallback = [this, notifycallback]() {
13723b3eb3cSopenharmony_ci            keepingIdle_ = false;
13823b3eb3cSopenharmony_ci            notifycallback();
13923b3eb3cSopenharmony_ci        };
14023b3eb3cSopenharmony_ci    }
14123b3eb3cSopenharmony_ci    if (keepingIdle_) {
14223b3eb3cSopenharmony_ci        notifycallback();
14323b3eb3cSopenharmony_ci    } else {
14423b3eb3cSopenharmony_ci        std::lock_guard<std::mutex> lock(observersMutex_);
14523b3eb3cSopenharmony_ci        pendingIdleObservers_.emplace_back(notifycallback);
14623b3eb3cSopenharmony_ci    }
14723b3eb3cSopenharmony_ci}
14823b3eb3cSopenharmony_ci
14923b3eb3cSopenharmony_civoid IdleWatcher::RequestContinuousIdleStatusNotification(IdleNotifycallback&& continuousIdleCallback)
15023b3eb3cSopenharmony_ci{
15123b3eb3cSopenharmony_ci    continuousIdleCallback_ = std::move(continuousIdleCallback);
15223b3eb3cSopenharmony_ci}
15323b3eb3cSopenharmony_ci
15423b3eb3cSopenharmony_civoid IdleWatcher::ClaimLongOperation()
15523b3eb3cSopenharmony_ci{
15623b3eb3cSopenharmony_ci    ComponentTestManagerImpl::Get()->pipelineStatusHolder.IncreaseLongOpt();
15723b3eb3cSopenharmony_ci}
15823b3eb3cSopenharmony_ci
15923b3eb3cSopenharmony_civoid IdleWatcher::LongOperationComplete()
16023b3eb3cSopenharmony_ci{
16123b3eb3cSopenharmony_ci    ComponentTestManagerImpl::Get()->pipelineStatusHolder.DecreaseLongOpt();
16223b3eb3cSopenharmony_ci}
16323b3eb3cSopenharmony_ci} // namespace OHOS::Ace::ComponentTest
164