/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "suspend_controller.h"
#include <datetime_ex.h>
#include <display_manager_lite.h>
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
#include <hisysevent.h>
#endif
#ifdef HAS_MULTIMODALINPUT_INPUT_PART
#include <input_manager.h>
#endif
#include <ipc_skeleton.h>
#include <securec.h>
#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
#include <screen_manager_lite.h>
#endif
#include "power_log.h"
#include "power_mgr_service.h"
#include "power_state_callback_stub.h"
#include "power_utils.h"
#include "setting_helper.h"
#include "system_suspend_controller.h"
#include "wakeup_controller.h"

namespace OHOS {
namespace PowerMgr {
using namespace OHOS::MMI;
namespace {
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
sptr<SettingObserver> g_suspendSourcesKeyAcObserver = nullptr;
sptr<SettingObserver> g_suspendSourcesKeyDcObserver = nullptr;
constexpr int64_t POWER_SLEEP_DEFAULT_TIME = 60000; // ms
constexpr int64_t POWER_SLEEP_NEVER = -1;
constexpr int64_t POWER_SLEEP_NOW = 0;
#else
sptr<SettingObserver> g_suspendSourcesKeyObserver = nullptr;
#endif
FFRTMutex g_monitorMutex;
constexpr int64_t POWERKEY_MIN_INTERVAL = 350; // ms
constexpr int32_t RETRY_COUNT_TIMES = 4;
constexpr int32_t RETRY_INTERVAL_MS = 100;
int32_t g_powerkeyReleaseIdCache = 3301; // SA_ID
} // namespace

std::atomic_bool onForceSleep = false;

/** SuspendController Implement */
SuspendController::SuspendController(const std::shared_ptr<ShutdownController>& shutdownController,
    const std::shared_ptr<PowerStateMachine>& stateMachine, const std::shared_ptr<FFRTTimer>& ffrtTimer)
{
    shutdownController_ = shutdownController;
    stateMachine_ = stateMachine;
    ffrtTimer_ = ffrtTimer;
}

SuspendController::~SuspendController()
{
    UnregisterSettingsObserver();
    ffrtTimer_.reset();
}

void SuspendController::AddCallback(const sptr<ISyncSleepCallback>& callback, SleepPriority priority)
{
    RETURN_IF(callback == nullptr)
    SleepCallbackHolder::GetInstance().AddCallback(callback, priority);
    POWER_HILOGI(FEATURE_SUSPEND,
        "sync sleep callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
        IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
}

void SuspendController::RemoveCallback(const sptr<ISyncSleepCallback>& callback)
{
    RETURN_IF(callback == nullptr)
    SleepCallbackHolder::GetInstance().RemoveCallback(callback);
    POWER_HILOGI(FEATURE_SUSPEND,
        "sync sleep callback removed, pid=%{public}d, uid=%{public}d",
        IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
}

#ifdef POWER_MANAGER_TAKEOVER_SUSPEND
void SuspendController::AddCallback(const sptr<ITakeOverSuspendCallback>& callback, TakeOverSuspendPriority priority)
{
    if (callback == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "callback is nullptr");
        return;
    }
    TakeOverSuspendCallbackHolder::GetInstance().AddCallback(callback, priority);
    POWER_HILOGI(FEATURE_SUSPEND,
        "TakeOver Suspend callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
        IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
}

void SuspendController::RemoveCallback(const sptr<ITakeOverSuspendCallback>& callback)
{
    if (callback == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "callback is nullptr");
        return;
    }
    TakeOverSuspendCallbackHolder::GetInstance().RemoveCallback(callback);
    POWER_HILOGI(FEATURE_SUSPEND,
        "TakeOver Suspend callback removed, pid=%{public}d, uid=%{public}d",
        IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
}
#endif

void SuspendController::TriggerSyncSleepCallback(bool isWakeup)
{
    std::lock_guard lock(sleepCbMutex_);
    POWER_HILOGI(FEATURE_SUSPEND, "TriggerSyncSleepCallback, isWakeup=%{public}d, onForceSleep=%{public}d", isWakeup,
        onForceSleep == true);
    auto highPriorityCallbacks = SleepCallbackHolder::GetInstance().GetHighPriorityCallbacks();
    TriggerSyncSleepCallbackInner(highPriorityCallbacks, "High", isWakeup);
    auto defaultPriorityCallbacks = SleepCallbackHolder::GetInstance().GetDefaultPriorityCallbacks();
    TriggerSyncSleepCallbackInner(defaultPriorityCallbacks, "Default", isWakeup);
    auto lowPriorityCallbacks = SleepCallbackHolder::GetInstance().GetLowPriorityCallbacks();
    TriggerSyncSleepCallbackInner(lowPriorityCallbacks, "Low", isWakeup);

    if (isWakeup && onForceSleep) {
        onForceSleep = false;
    }
}

void SuspendController::TriggerSyncSleepCallbackInner(
    SleepCallbackHolder::SleepCallbackContainerType& callbacks, const std::string& priority, bool isWakeup)
{
    uint32_t id = 0;
    for (auto &callback : callbacks) {
        auto pidUid = SleepCallbackHolder::GetInstance().FindCallbackPidUid(callback);
        if (callback != nullptr) {
            int64_t start = GetTickCount();
            POWER_HILOGI(FEATURE_SUSPEND, "Sync Sleep Callback, pid=%{public}d", pidUid.first);
            isWakeup ? callback->OnSyncWakeup(onForceSleep) : callback->OnSyncSleep(onForceSleep);
            int64_t cost = GetTickCount() - start;
            POWER_HILOGI(FEATURE_SUSPEND,
                "Trigger %{public}s SyncSleepCb[%{public}u] success,P=%{public}dU=%{public}dT=%{public}" PRId64,
                priority.c_str(), ++id, pidUid.first, pidUid.second, cost);
        }
    }
}

#ifdef POWER_MANAGER_TAKEOVER_SUSPEND
bool SuspendController::TriggerTakeOverSuspendCallback(SuspendDeviceType type)
{
    bool isTakeover = false;
    POWER_HILOGI(FEATURE_SUSPEND, "TriggerTakeOverSuspendCallback, type=%{public}d", type);
    auto highPriorityCallbacks = TakeOverSuspendCallbackHolder::GetInstance().GetHighPriorityCallbacks();
    isTakeover = TriggerTakeOverSuspendCallbackInner(highPriorityCallbacks, "High", type);
    RETURN_IF_WITH_RET(isTakeover, true);
    auto defaultPriorityCallbacks = TakeOverSuspendCallbackHolder::GetInstance().GetDefaultPriorityCallbacks();
    isTakeover = TriggerTakeOverSuspendCallbackInner(defaultPriorityCallbacks, "Default", type);
    RETURN_IF_WITH_RET(isTakeover, true);
    auto lowPriorityCallbacks = TakeOverSuspendCallbackHolder::GetInstance().GetLowPriorityCallbacks();
    isTakeover = TriggerTakeOverSuspendCallbackInner(lowPriorityCallbacks, "Low", type);
    return isTakeover;
}

bool SuspendController::TriggerTakeOverSuspendCallbackInner(
    TakeOverSuspendCallbackHolder::TakeoverSuspendCallbackContainerType& callbacks,
    const std::string& priority, SuspendDeviceType type)
{
    uint32_t id = 0;
    bool isTakeover = false;
    if (callbacks.size() == 0) {
        POWER_HILOGI(FEATURE_SUSPEND, "callbacks size is zero");
        return isTakeover;
    }
    for (const auto& callback : callbacks) {
        if (callback == nullptr) {
            POWER_HILOGE(FEATURE_SUSPEND, "callback is nullptr");
            continue;
        }
        auto pidUid = TakeOverSuspendCallbackHolder::GetInstance().FindCallbackPidUid(callback);
        int64_t start = GetTickCount();
        isTakeover = isTakeover || callback->OnTakeOverSuspend(type);
        int64_t count = GetTickCount() - start;
        POWER_HILOGI(FEATURE_SUSPEND,
            "Trigger %{public}s takeovercb [%{public}u] success, P=%{public}d U=%{public}d T=%{public}" PRId64,
            priority.c_str(), ++id, pidUid.first, pidUid.second, count);
    }
    return isTakeover;
}
#endif

class SuspendPowerStateCallback : public PowerStateCallbackStub {
public:
    explicit SuspendPowerStateCallback(std::shared_ptr<SuspendController> controller) : controller_(controller) {};
    virtual ~SuspendPowerStateCallback() = default;
    void OnPowerStateChanged(PowerState state) override
    {
        auto controller = controller_.lock();
        if (controller == nullptr) {
            POWER_HILOGI(FEATURE_SUSPEND, "OnPowerStateChanged: No controller");
            return;
        }
        if (state == PowerState::AWAKE) {
            POWER_HILOGI(FEATURE_SUSPEND, "Turn awake, stop sleep timer");
            controller->StopSleep();
        }
    }

private:
    std::weak_ptr<SuspendController> controller_;
};

void SuspendController::Init()
{
    std::lock_guard lock(mutex_);
    std::shared_ptr<SuspendSources> sources = SuspendSourceParser::ParseSources();
    sourceList_ = sources->GetSourceList();
    if (sourceList_.empty()) {
        POWER_HILOGE(FEATURE_SUSPEND, "InputManager is null");
        return;
    }

    for (auto source = sourceList_.begin(); source != sourceList_.end(); source++) {
        POWER_HILOGI(FEATURE_SUSPEND, "registered type=%{public}u action=%{public}u delayMs=%{public}u",
            (*source).GetReason(), (*source).GetAction(), (*source).GetDelay());
        std::shared_ptr<SuspendMonitor> monitor = SuspendMonitor::CreateMonitor(*source);
        if (monitor == nullptr) continue;
        monitor->RegisterListener([this](SuspendDeviceType reason, uint32_t action, uint32_t delay) {
            this->ControlListener(reason, action, delay);
        });
        if (monitor != nullptr && monitor->Init()) {
            POWER_HILOGI(FEATURE_SUSPEND, "monitor init success, type=%{public}u", (*source).GetReason());
            g_monitorMutex.lock();
            monitorMap_.emplace(monitor->GetReason(), monitor);
            g_monitorMutex.unlock();
        }
    }
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
        return;
    }

    sptr<SuspendPowerStateCallback> callback = new SuspendPowerStateCallback(shared_from_this());
    stateMachine_->RegisterPowerStateCallback(callback);
    if (suspendPowerStateCallback_ != nullptr) {
        stateMachine_->UnRegisterPowerStateCallback(suspendPowerStateCallback_);
    }
    suspendPowerStateCallback_ = callback;

    RegisterSettingsObserver();
}

void SuspendController::ExecSuspendMonitorByReason(SuspendDeviceType reason)
{
    FFRTTask suspendTask = [this, reason]() {
        g_monitorMutex.lock();
        auto suspendMonitor = GetSpecifiedSuspendMonitor(reason);
        if (suspendMonitor == nullptr) {
            POWER_HILOGI(COMP_SVC, "get monitor fail, type: %{public}u", reason);
            g_monitorMutex.unlock();
            return;
        }
        suspendMonitor->Notify();
        g_monitorMutex.unlock();
    };

    if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH) {
        // make sure that open/close switch tasks are processed in the order they were created
        POWER_HILOGI(FEATURE_SUSPEND, "switch trigger suspend");
        stateMachine_->SetDelayTimer(0, PowerStateMachine::SWITCH_TRIGGER_WAKEUP_OR_SUSPEND_MSG, suspendTask);
    } else {
        FFRTUtils::SubmitTask(suspendTask);
    }
}

void SuspendController::UpdateSuspendSources()
{
    POWER_HILOGI(COMP_SVC, "start setting string update");
    std::lock_guard lock(mutex_);

    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(COMP_SVC, "get PowerMgrService fail");
        return;
    }
    std::string jsonStr;
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (pms->IsPowerConnected()) {
        jsonStr = SettingHelper::GetSettingAcSuspendSources();
    } else {
        jsonStr = SettingHelper::GetSettingDcSuspendSources();
    }
#else
    jsonStr = SettingHelper::GetSettingSuspendSources();
#endif
    std::shared_ptr<SuspendSources> sources = SuspendSourceParser::ParseSources(jsonStr);
    if (sources->GetParseErrorFlag()) {
        POWER_HILOGI(FEATURE_SUSPEND, "Parse failed, call GetSuspendSourcesByConfig again");
        jsonStr = SuspendSourceParser::GetSuspendSourcesByConfig();
        sources = SuspendSourceParser::ParseSources(jsonStr);
    }
    if (sources == nullptr) {
        POWER_HILOGE(COMP_SVC, "get SuspendSources fail");
        return;
    }
    std::vector<SuspendSource> updateSourceList = sources->GetSourceList();
    if (updateSourceList.size() == 0) {
        return;
    }
    sourceList_ = updateSourceList;
    POWER_HILOGI(COMP_SVC, "start updateListener");
    Cancel();
    uint32_t id = 0;
    for (auto source = sourceList_.begin(); source != sourceList_.end(); source++, id++) {
        std::shared_ptr<SuspendMonitor> monitor = SuspendMonitor::CreateMonitor(*source);
        if (monitor == nullptr) continue;
        monitor->RegisterListener([this](SuspendDeviceType reason, uint32_t action, uint32_t delay) {
            this->ControlListener(reason, action, delay);
        });
        POWER_HILOGI(FEATURE_SUSPEND, "Update CreateMonitor[%{public}u] reason=%{public}d", id, source->GetReason());
        if (monitor != nullptr && monitor->Init()) {
            g_monitorMutex.lock();
            monitorMap_.emplace(monitor->GetReason(), monitor);
            g_monitorMutex.unlock();
        }
    }
}

void SuspendController::RegisterSettingsObserver()
{
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_suspendSourcesKeyAcObserver && g_suspendSourcesKeyDcObserver) {
#else
    if (g_suspendSourcesKeyObserver) {
#endif
        POWER_HILOGE(FEATURE_POWER_STATE, "suspend sources key observer is already registered");
        return;
    }
    SettingObserver::UpdateFunc updateFunc = [&](const std::string&) {
        SuspendController::UpdateSuspendSources();
    };
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_suspendSourcesKeyAcObserver == nullptr) {
        g_suspendSourcesKeyAcObserver = SettingHelper::RegisterSettingAcSuspendSourcesObserver(updateFunc);
    }
    if (g_suspendSourcesKeyDcObserver == nullptr) {
        g_suspendSourcesKeyDcObserver = SettingHelper::RegisterSettingDcSuspendSourcesObserver(updateFunc);
    }
#else
    g_suspendSourcesKeyObserver = SettingHelper::RegisterSettingSuspendSourcesObserver(updateFunc);
#endif
    POWER_HILOGI(FEATURE_POWER_STATE, "register setting observer fin");
}

void SuspendController::UnregisterSettingsObserver()
{
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_suspendSourcesKeyAcObserver) {
        SettingHelper::UnregisterSettingObserver(g_suspendSourcesKeyAcObserver);
        g_suspendSourcesKeyAcObserver = nullptr;
    }
    if (g_suspendSourcesKeyDcObserver) {
        SettingHelper::UnregisterSettingObserver(g_suspendSourcesKeyDcObserver);
        g_suspendSourcesKeyDcObserver = nullptr;
    }
#else
    if (g_suspendSourcesKeyObserver) {
        SettingHelper::UnregisterSettingObserver(g_suspendSourcesKeyObserver);
        g_suspendSourcesKeyObserver = nullptr;
    }
#endif
}

void SuspendController::Execute()
{
    HandleAction(GetLastReason(), GetLastAction());
}

void SuspendController::Cancel()
{
    g_monitorMutex.lock();
    for (auto monitor = monitorMap_.begin(); monitor != monitorMap_.end(); monitor++) {
        monitor->second->Cancel();
    }
    monitorMap_.clear();
    g_monitorMutex.unlock();
}

void SuspendController::StopSleep()
{
    if (ffrtTimer_ != nullptr) {
        ffrtTimer_->CancelTimer(TIMER_ID_SLEEP);
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
        POWER_HILOGI(FEATURE_POWER_STATE, "stop auto sleep");
        ffrtTimer_->CancelTimer(TIMER_ID_AUTO_SLEEP);
#endif
    }
    ffrtMutexMap_.Lock(TIMER_ID_SLEEP);
    sleepTime_ = -1;
    sleepAction_ = static_cast<uint32_t>(SuspendAction::ACTION_NONE);
    ffrtMutexMap_.Unlock(TIMER_ID_SLEEP);
}

void SuspendController::HandleEvent(int64_t delayTime)
{
    FFRTTask task = [&]() {
        g_monitorMutex.lock();
        auto timeoutSuspendMonitor = GetSpecifiedSuspendMonitor(SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT);
        if (timeoutSuspendMonitor == nullptr) {
            g_monitorMutex.unlock();
            return;
        }

        auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
        if (pms != nullptr) {
            if (pms->CheckDialogFlag()) {
                POWER_HILOGI(FEATURE_SUSPEND, "Reset long press flag before suspending device by timeout");
            }
        }
        if (stateMachine_ != nullptr) {
            int32_t timeout = stateMachine_->GetDisplayOffTime();
            POWER_HILOGI(FEATURE_INPUT, "This time of timeout is %{public}d ms", timeout);
        }
        g_monitorMutex.unlock();
        timeoutSuspendMonitor->HandleEvent();
    };
    if (ffrtTimer_ != nullptr) {
        ffrtTimer_->SetTimer(TIMER_ID_USER_ACTIVITY_OFF, task, delayTime);
    } else {
        POWER_HILOGE(FEATURE_SUSPEND, "%{public}s: SetTimer(%{public}s) failed, timer is null", __func__,
            std::to_string(delayTime).c_str());
    }
}

void SuspendController::CancelEvent()
{
    if (ffrtTimer_ != nullptr) {
        ffrtTimer_->CancelTimer(TIMER_ID_USER_ACTIVITY_OFF);
    }
}

void SuspendController::RecordPowerKeyDown(bool interrupting)
{
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
        return;
    }
    bool isScreenOn = stateMachine_->IsScreenOn();
    POWER_HILOGI(FEATURE_SUSPEND, "Suspend record key down action isScreenOn=%{public}d", isScreenOn);
    if (!isScreenOn) {
        powerkeyDownWhenScreenOff_ = true;
    } else {
        if (interrupting) {
            POWER_HILOGI(FEATURE_SUSPEND, "Suspend record key down after interrupting screen off");
        }
        powerkeyDownWhenScreenOff_ = interrupting;
    }

    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }

    if (pms->CheckDialogFlag()) {
        return;
    }
}

bool SuspendController::GetPowerkeyDownWhenScreenOff()
{
    bool powerKeyDown = powerkeyDownWhenScreenOff_;
    powerkeyDownWhenScreenOff_ = false;
    return powerKeyDown;
}

void SuspendController::SuspendWhenScreenOff(SuspendDeviceType reason, uint32_t action, uint32_t delay)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    RETURN_IF(pms == nullptr);
    if ((pms->IsLidCheckEnable() && reason != SuspendDeviceType::SUSPEND_DEVICE_REASON_LID) ||
        (!pms->IsLidCheckEnable() && reason != SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH)) {
        POWER_HILOGI(FEATURE_SUSPEND, "SuspendWhenScreenOff: Do nothing for reason %{public}u", reason);
        return;
    }
    if (stateMachine_ == nullptr) {
        return;
    }

    POWER_HILOGI(FEATURE_SUSPEND,
        "Suspend when screen off, reason=%{public}d, action=%{public}u, "
        "delay=%{public}u, state=%{public}d, type=%{public}u",
        reason, action, delay, stateMachine_->GetState(), sleepType_);
    switch (stateMachine_->GetState()) {
        case PowerState::INACTIVE:
            StopSleep();
            StartSleepTimer(reason, action, delay);
            break;
        case PowerState::SLEEP:
            SuspendWhenStateSleep(reason, action);
            break;
        default:
            break;
    }
}

void SuspendController::SuspendWhenStateSleep(SuspendDeviceType reason, uint32_t action)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }
    if (action == static_cast<uint32_t>(SuspendAction::ACTION_HIBERNATE)) {
        POWER_HILOGI(FEATURE_SUSPEND, "SuspendWhenStateSleep for hibernate");
        SystemSuspendController::GetInstance().Wakeup();
        StartSleepTimer(reason, action, 0);
        return;
    }
    if (action != static_cast<uint32_t>(SuspendAction::ACTION_FORCE_SUSPEND)) {
        return;
    }
    if (sleepType_ == static_cast<uint32_t>(SuspendAction::ACTION_AUTO_SUSPEND)) {
        SystemSuspendController::GetInstance().Wakeup();
        StartSleepTimer(reason, action, 0);
    } else if (sleepType_ == static_cast<uint32_t>(SuspendAction::ACTION_FORCE_SUSPEND)) {
        if ((pms->IsLidCheckEnable() && PowerMgrService::isInLidMode_ == false) ||
            (!pms->IsLidCheckEnable() && stateMachine_->IsSwitchOpen())) {
            POWER_HILOGI(FEATURE_SUSPEND, "switch off event is ignored.");
            return;
        }
        SystemSuspendController::GetInstance().Wakeup();
        SystemSuspendController::GetInstance().Suspend([]() {}, []() {}, true);
    } else {
        POWER_HILOGD(FEATURE_SUSPEND, "Nothing to do for no suspend");
    }
}

void SuspendController::ControlListener(SuspendDeviceType reason, uint32_t action, uint32_t delay)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "get PowerStateMachine instance error");
        return;
    }

    if (pms->CheckDialogAndShuttingDown()) {
        return;
    }

    if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH) {
        stateMachine_->SetSwitchAction(action);
    }
    bool isScreenOn = stateMachine_->IsScreenOn();
    if (!isScreenOn) {
        SuspendWhenScreenOff(reason, action, delay);
        return;
    }

#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
    if (IsPowerOffInernalScreenOnlyScene(reason, static_cast<SuspendAction>(action), isScreenOn)) {
        ProcessPowerOffInternalScreenOnly(pms, reason);
        return;
    }
#endif
    if (CheckDuringCall(pms, reason)) {
        return;
    }
    pid_t pid = IPCSkeleton::GetCallingPid();
    auto uid = IPCSkeleton::GetCallingUid();
    uint32_t ffrtId = ffrt::this_task::get_id();
    POWER_HILOGI(FEATURE_SUSPEND,
        "[UL_POWER] Try to suspend device, pid=%{public}d, uid=%{public}d, reason=%{public}d, action=%{public}u, "
        "delay=%{public}u, ffrtId=%{public}u",
        pid, uid, reason, action, delay, ffrtId);
    bool force = true;
    if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT) {
        force = false;
    }
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    stateMachine_->ReportSuspendStart(static_cast<int32_t>(uid), static_cast<int32_t>(reason), force);
#endif
    bool ret = stateMachine_->SetState(
        PowerState::INACTIVE, stateMachine_->GetReasonBySuspendType(static_cast<SuspendDeviceType>(reason)), force);
    if (ret) {
        StartSleepTimer(reason, action, delay);
    }
}

bool SuspendController::CheckDuringCall(const sptr<PowerMgrService>& pms, SuspendDeviceType reason)
{
    if (pms->IsDuringCallStateEnable()) {
        if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_POWER_KEY &&
            Rosen::DisplayManagerLite::GetInstance().GetFoldDisplayMode() == Rosen::FoldDisplayMode::SUB &&
            stateMachine_->HandleDuringCall(false)) {
            POWER_HILOGI(FEATURE_SUSPEND, "switch to main display when duringcall mode");
            return true;
        }
    }
    return false;
}

std::shared_ptr<SuspendMonitor> SuspendController::GetSpecifiedSuspendMonitor(SuspendDeviceType type) const
{
    auto iter = monitorMap_.find(type);
    if (iter == monitorMap_.end()) {
        return nullptr;
    }
    return iter->second;
}

#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
void SuspendController::PowerOffInternalScreen(SuspendDeviceType type)
{
    stateMachine_->SetInternalScreenDisplayState(
        DisplayState::DISPLAY_OFF, stateMachine_->GetReasonBySuspendType(type));
}

void SuspendController::PowerOffAllScreens(SuspendDeviceType type)
{
    using namespace OHOS::Rosen;
    auto changeReason = stateMachine_->GetReasonBySuspendType(type);
    auto dmsReason = PowerUtils::GetDmsReasonByPowerReason(changeReason);
    bool ret = ScreenManagerLite::GetInstance().SetScreenPowerForAll(ScreenPowerState::POWER_OFF, dmsReason);
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    if (!ret) {
        std::string eventReason = "PowerOffAllScreens failed";
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "ABNORMAL_FAULT",
            HiviewDFX::HiSysEvent::EventType::FAULT, "TYPE", "EXTERNAL_SCREEN", "REASON", eventReason);
    }
#endif
    POWER_HILOGI(
        FEATURE_SUSPEND, "[UL_POWER] Power off all screens, reason = %{public}u, ret = %{public}d", dmsReason, ret);
}

bool SuspendController::IsPowerOffInernalScreenOnlyScene(
    SuspendDeviceType reason, SuspendAction action, bool isScreenOn) const
{
    if (reason == SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH && isScreenOn &&
        action == SuspendAction::ACTION_NONE && stateMachine_->GetExternalScreenNumber() > 0) {
        return true;
    }
    return false;
}

void SuspendController::ProcessPowerOffInternalScreenOnly(const sptr<PowerMgrService>& pms, SuspendDeviceType reason)
{
    POWER_HILOGI(
        FEATURE_SUSPEND, "[UL_POWER] Power off internal screen when closing switch is configured as no operation");
    PowerOffInternalScreen(reason);
    pms->RefreshActivity(GetTickCount(), UserActivityType::USER_ACTIVITY_TYPE_SWITCH, false);
}
#endif

void SuspendController::StartSleepTimer(SuspendDeviceType reason, uint32_t action, uint32_t delay)
{
    if (static_cast<SuspendAction>(action) == SuspendAction::ACTION_AUTO_SUSPEND) {
        if (stateMachine_->GetSleepTime() < 0) {
            POWER_HILOGI(FEATURE_SUSPEND, "sleeptime less than zero, no need suspend");
            return;
        }
    }

    int64_t tick = GetTickCount();
    int64_t timeout = tick + static_cast<int64_t>(delay);
    if (timeout < tick) {
        POWER_HILOGE(FEATURE_SUSPEND, "Sleep timer overflow with tick = %{public}s, delay = %{public}u",
            std::to_string(tick).c_str(), delay);
        return;
    }

    if ((timeout > sleepTime_) && (sleepTime_ != -1)) {
        POWER_HILOGI(FEATURE_SUSPEND, "already have a sleep event (%{public}" PRId64 " > %{public}" PRId64 ")", timeout,
            sleepTime_);
        return;
    }
    ffrtMutexMap_.Lock(TIMER_ID_SLEEP);
    sleepTime_ = timeout;
    sleepReason_ = reason;
    sleepAction_ = action;
    sleepDuration_ = delay;
    sleepType_ = action;
    ffrtMutexMap_.Unlock(TIMER_ID_SLEEP);
    FFRTTask task = [this, reason, action] {
        HandleAction(reason, action);
    };

    if (ffrtTimer_ != nullptr) {
        ffrtTimer_->SetTimer(TIMER_ID_SLEEP, task, delay);
    } else {
        POWER_HILOGE(FEATURE_SUSPEND, "%{public}s: SetTimer(%{public}u) failed, timer is null", __func__, delay);
    }
}

void SuspendController::HandleAction(SuspendDeviceType reason, uint32_t action)
{
    switch (static_cast<SuspendAction>(action)) {
        case SuspendAction::ACTION_AUTO_SUSPEND:
            HandleAutoSleep(reason);
            break;
        case SuspendAction::ACTION_FORCE_SUSPEND:
            HandleForceSleep(reason);
            break;
        case SuspendAction::ACTION_HIBERNATE:
            HandleHibernate(reason);
            break;
        case SuspendAction::ACTION_SHUTDOWN:
            HandleShutdown(reason);
            break;
        case SuspendAction::ACTION_NONE:
        default:
            break;
    }
    ffrtMutexMap_.Lock(TIMER_ID_SLEEP);
    sleepTime_ = -1;
    sleepAction_ = static_cast<uint32_t>(SuspendAction::ACTION_NONE);
    ffrtMutexMap_.Unlock(TIMER_ID_SLEEP);
}

#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
int64_t SuspendController::GetSettingPowerSleepTime(int64_t defaultTime)
{
    int64_t settingTime = defaultTime;
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_MODE, "get PowerMgrService fail");
        return settingTime;
    }
    if (pms->IsPowerConnected()) {
        settingTime = SettingHelper::GetSettingPowerAcSleepTime(defaultTime);
    } else {
        settingTime = SettingHelper::GetSettingPowerDcSleepTime(defaultTime);
    }
    return settingTime;
}

int64_t SuspendController::CalculateAutoSleepResult()
{
    int64_t displayOffTime = 0;
    int64_t powerSleepTime = 0;
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms != nullptr) {
        displayOffTime = pms->GetSettingDisplayOffTime(POWER_SLEEP_DEFAULT_TIME);
    }
    powerSleepTime = GetSettingPowerSleepTime(POWER_SLEEP_DEFAULT_TIME);
    POWER_HILOGI(FEATURE_SUSPEND, "%{public}s: displayOffTime(%{public}ld), powerSleepTime(%{public}ld)",
        __func__, displayOffTime, powerSleepTime);
    if (powerSleepTime == POWER_SLEEP_NEVER) {
        return POWER_SLEEP_NEVER;
    }
    if (powerSleepTime <= displayOffTime) {
        return POWER_SLEEP_NOW;
    }
    return powerSleepTime - displayOffTime;
}
#endif

void SuspendController::HandleAutoSleep(SuspendDeviceType reason)
{
    POWER_HILOGI(FEATURE_SUSPEND, "auto suspend by reason=%{public}d", reason);
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    int64_t autoSleepResult = CalculateAutoSleepResult();
    if (autoSleepResult == POWER_SLEEP_NEVER) {
        POWER_HILOGI(FEATURE_SUSPEND, "power sleep is never");
        return;
    }
    if (autoSleepResult == POWER_SLEEP_NOW) {
        POWER_HILOGI(FEATURE_SUSPEND, "start auto sleep");
        SetAutoSleep(reason);
        return;
    }
    uint32_t delay = static_cast<uint32_t>(autoSleepResult);
    FFRTTask task = [this, reason] {
        SetAutoSleep(reason);
    };
    if (ffrtTimer_ != nullptr) {
        ffrtTimer_->SetTimer(TIMER_ID_AUTO_SLEEP, task, delay);
    } else {
        POWER_HILOGE(FEATURE_SUSPEND, "%{public}s: SetTimer(%{public}d) failed, timer is null",
            __func__, delay);
    }
#else
    SetAutoSleep(reason);
#endif
}

void SuspendController::SetAutoSleep(SuspendDeviceType reason)
{
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
        return;
    }
    bool ret = stateMachine_->SetState(
        PowerState::SLEEP, stateMachine_->GetReasonBySuspendType(reason));
    if (ret && stateMachine_->GetState() == PowerState::SLEEP) {
        POWER_HILOGI(FEATURE_SUSPEND, "State changed, set sleep timer");
        TriggerSyncSleepCallback(false);
        SystemSuspendController::GetInstance().Suspend([]() {}, []() {}, false);
    } else {
        POWER_HILOGI(FEATURE_SUSPEND, "auto suspend: State change failed");
    }
}

void SuspendController::HandleForceSleep(SuspendDeviceType reason)
{
    POWER_HILOGI(FEATURE_SUSPEND, "force suspend by reason=%{public}d", reason);
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
        return;
    }

#ifdef POWER_MANAGER_ENABLE_FORCE_SLEEP_BROADCAST
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms != nullptr && pms->GetSuspendController() != nullptr) {
        pms->GetSuspendController()->SetForceSleepingFlag(true);
        POWER_HILOGI(FEATURE_SUSPEND, "Set flag of force sleeping to true");
    } else {
        POWER_HILOGE(FEATURE_SUSPEND, "Failed to set flag of force sleeping, pms or suspendController is nullptr");
    }
#endif
    bool ret = stateMachine_->SetState(PowerState::SLEEP,
        stateMachine_->GetReasonBySuspendType(reason), true);
    if (ret) {
        POWER_HILOGI(FEATURE_SUSPEND, "State changed, system suspend");
        onForceSleep = true;
        TriggerSyncSleepCallback(false);

        FFRTTask task = [this, reason] {
            if (stateMachine_->GetState() == PowerState::SLEEP) {
                SystemSuspendController::GetInstance().Suspend([]() {}, []() {}, true);
            } else {
                POWER_HILOGE(FEATURE_SUSPEND, "Don't suspend, power state is not sleep");
            }
        };
        if (ffrtTimer_ != nullptr) {
            ffrtTimer_->SetTimer(TIMER_ID_SLEEP, task, FORCE_SLEEP_DELAY_MS);
        } else {
            POWER_HILOGE(FEATURE_SUSPEND, "%{public}s: SetTimer(%{public}d) failed, timer is null",
                __func__, FORCE_SLEEP_DELAY_MS);
        }
    } else {
        POWER_HILOGI(FEATURE_SUSPEND, "force suspend: State change failed");
    }
}

void SuspendController::HandleHibernate(SuspendDeviceType reason)
{
    POWER_HILOGI(FEATURE_SUSPEND, "hibernate by reason=%{public}d", reason);
    if (stateMachine_ == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerStateMachine");
        return;
    }
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Can't get PowerMgrService");
        return;
    }
    // State machine transitions are driven entirely by HibernateInner:
    //   current -> INACTIVE -> HIBERNATE -> AWAKE
    // Do not pre-SetState(HIBERNATE) here to avoid the redundant
    // HIBERNATE -> INACTIVE -> HIBERNATE sequence within the same call stack.
    StateChangeReason stateReason = stateMachine_->GetReasonBySuspendType(reason);
    std::string reasonStr = PowerUtils::GetReasonTypeString(stateReason);
    PowerErrors hibernateRet = pms->Hibernate(false, reasonStr);
    if (hibernateRet != PowerErrors::ERR_OK) {
        POWER_HILOGE(FEATURE_SUSPEND, "Hibernate failed, ret=%{public}d", static_cast<int32_t>(hibernateRet));
    }
}

void SuspendController::HandleShutdown(SuspendDeviceType reason)
{
    POWER_HILOGI(FEATURE_SUSPEND, "shutdown by reason=%{public}d", reason);
    shutdownController_->Shutdown(std::to_string(static_cast<uint32_t>(reason)));
}

void SuspendController::Reset()
{
    ffrtTimer_.reset();
}

#ifdef POWER_MANAGER_WAKEUP_ACTION
bool SuspendController::GetWakeupReasonConfigMatchedFlag()
{
    return isWakeupReasonConfigMatched_;
}

void SuspendController::SetWakeupReasonConfigMatchedFlag(bool flag)
{
    isWakeupReasonConfigMatched_ = flag;
}
#endif

int32_t SuspendController::GetPowerkeyReleaseIdCache()
{
    return g_powerkeyReleaseIdCache;
}

const std::shared_ptr<SuspendMonitor> SuspendMonitor::CreateMonitor(SuspendSource& source)
{
    SuspendDeviceType reason = source.GetReason();
    std::shared_ptr<SuspendMonitor> monitor = nullptr;
    switch (reason) {
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_POWER_KEY:
            monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<PowerKeySuspendMonitor>(source));
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT:
            monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<TimeoutSuspendMonitor>(source));
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_LID:
            monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<LidSuspendMonitor>(source));
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH:
            monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<SwitchSuspendMonitor>(source));
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_TP_COVER:
            monitor = std::static_pointer_cast<SuspendMonitor>(std::make_shared<TPCoverSuspendMonitor>(source));
            break;
        default:
            POWER_HILOGE(FEATURE_SUSPEND, "CreateMonitor : Invalid reason=%{public}d", reason);
            break;
    }
    return monitor;
}

/** PowerKeySuspendMonitor Implement */
bool PowerKeySuspendMonitor::Init()
{
#ifdef HAS_MULTIMODALINPUT_INPUT_PART
    if (powerkeyReleaseId_ >= 0) {
        return true;
    }
    std::shared_ptr<OHOS::MMI::KeyOption> keyOption = std::make_shared<OHOS::MMI::KeyOption>();
    if (keyOption == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "keyOption is nullptr");
        return false;
    }
    std::set<int32_t> preKeys;
    keyOption->SetPreKeys(preKeys);
    keyOption->SetFinalKey(OHOS::MMI::KeyEvent::KEYCODE_POWER);
    keyOption->SetFinalKeyDown(false);
    keyOption->SetFinalKeyDownDuration(0);
    auto inputManager = InputManager::GetInstance();
    if (!inputManager) {
        POWER_HILOGE(FEATURE_SUSPEND, "PowerKeySuspendMonitorInit inputManager is null");
        return false;
    }
    int32_t retryCount = 0;
    bool subscribeOrLastUnsubscribeFailed = false;
    do {
        inputManager->UnsubscribeKeyEvent(g_powerkeyReleaseIdCache);
        powerkeyReleaseId_ = inputManager->SubscribeKeyEvent(
            keyOption, [*this](std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) {
                ReceivePowerkeyCallback(keyEvent);
            });
        subscribeOrLastUnsubscribeFailed =
            powerkeyReleaseId_ < 0 || powerkeyReleaseId_ == g_powerkeyReleaseIdCache;
        if (subscribeOrLastUnsubscribeFailed) {
            POWER_HILOGE(FEATURE_SUSPEND, "powerkey up retry, id:%{public}d cache:%{public}d count:%{public}d",
                powerkeyReleaseId_, g_powerkeyReleaseIdCache, retryCount);
            retryCount++;
            if (retryCount < RETRY_COUNT_TIMES) {
                std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL_MS));
            } else {
                POWER_HILOGE(FEATURE_SUSPEND, "trigger powerkeyupevent subscribe fail hiviewevent");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
                HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER,
                    "ABNORMAL_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT, "TYPE", "SCREEN_ON_OFF",
                    "REASON", "PowerkeyUpEvent Subscribe Fail");
#endif
            }
        }
    } while (subscribeOrLastUnsubscribeFailed && retryCount < RETRY_COUNT_TIMES);
    g_powerkeyReleaseIdCache = powerkeyReleaseId_;
    POWER_HILOGI(FEATURE_SUSPEND, "powerkeyReleaseId_=%{public}d", powerkeyReleaseId_);
    return powerkeyReleaseId_ >= 0 ? true : false;
#else
    return false;
#endif
}

void PowerKeySuspendMonitor::ReceivePowerkeyCallback(std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) const
{
    POWER_HILOGI(FEATURE_SUSPEND, "[UL_POWER] Received powerkey up");

    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "[UL_POWER] PowerMgrService is nullptr");
        return;
    }
    std::shared_ptr<SuspendController> suspendController = pms->GetSuspendController();
    if (suspendController == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "[UL_POWER] suspendController is nullptr");
        return;
    }
    std::shared_ptr<WakeupController> wakeupController = pms->GetWakeupController();
    if (wakeupController == nullptr) {
        POWER_HILOGE(FEATURE_WAKEUP, "[UL_POWER] wakeupController is nullptr");
        return;
    }

#if POWER_MANAGER_WAKEUP_ACTION
    bool isWakeupReasonConfigMatched = suspendController->GetWakeupReasonConfigMatchedFlag();
    if (isWakeupReasonConfigMatched
        || wakeupController->IsWakeupReasonConfigMatched(WakeupDeviceType::WAKEUP_DEVICE_POWER_BUTTON)) {
        POWER_HILOGI(FEATURE_SUSPEND, "[UL_POWER] wakeup reason matched config, skip powerkey up");
        suspendController->SetWakeupReasonConfigMatchedFlag(false);
        return;
    }
#endif

    static int64_t lastPowerkeyUpTime = 0;
    int64_t currTime = GetTickCount();
    if (lastPowerkeyUpTime != 0 && currTime - lastPowerkeyUpTime < POWERKEY_MIN_INTERVAL) {
        POWER_HILOGI(FEATURE_WAKEUP, "[UL_POWER] Last powerkey up within %{public}" PRId64 "ms, skip. "
            "%{public}" PRId64 ", %{public}" PRId64, POWERKEY_MIN_INTERVAL, currTime, lastPowerkeyUpTime);
        return;
    }
    lastPowerkeyUpTime = currTime;

    if (suspendController->GetPowerkeyDownWhenScreenOff()) {
        POWER_HILOGI(FEATURE_SUSPEND,
            "[UL_POWER] The powerkey was pressed when screenoff, ignore this powerkey up event.");
        return;
    }
    auto powerkeyScreenOffTask = [*this]() mutable {
        Notify();
        powerkeyScreenOff_ = false;
        EndPowerkeyScreenOff();
    };
    BeginPowerkeyScreenOff();
    powerkeyScreenOff_ = true;
    ffrt::submit(powerkeyScreenOffTask, {}, {&powerkeyScreenOff_});
    POWER_HILOGI(FEATURE_SUSPEND, "[UL_POWER] submitted screen off ffrt task");
}

void PowerKeySuspendMonitor::BeginPowerkeyScreenOff() const
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }
    auto stateMachine = pms->GetPowerStateMachine();
    if (stateMachine == nullptr) {
        return;
    }
    auto stateAction = stateMachine->GetStateAction();
    if (stateAction == nullptr) {
        return;
    }
    stateAction->BeginPowerkeyScreenOff();
}

void PowerKeySuspendMonitor::EndPowerkeyScreenOff() const
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }
    auto stateMachine = pms->GetPowerStateMachine();
    if (stateMachine == nullptr) {
        return;
    }
    auto stateAction = stateMachine->GetStateAction();
    if (stateAction == nullptr) {
        return;
    }
    stateAction->EndPowerkeyScreenOff();
}

void PowerKeySuspendMonitor::Cancel()
{
#ifdef HAS_MULTIMODALINPUT_INPUT_PART
    auto inputManager = InputManager::GetInstance();
    if (!inputManager) {
        POWER_HILOGE(FEATURE_SUSPEND, "PowerKeySuspendMonitorCancel inputManager is null");
        return;
    }
    if (powerkeyReleaseId_ >= 0) {
        POWER_HILOGI(FEATURE_SUSPEND, "UnsubscribeKeyEvent: PowerKeySuspendMonitor");
        inputManager->UnsubscribeKeyEvent(powerkeyReleaseId_);
        powerkeyReleaseId_ = -1;
    }
#endif
}

/** Timeout Implement */
bool TimeoutSuspendMonitor::Init()
{
    return true;
}

void TimeoutSuspendMonitor::Cancel() {}

void TimeoutSuspendMonitor::HandleEvent()
{
    POWER_HILOGI(FEATURE_INPUT, "TimeoutSuspendMonitor HandleEvent.");
    Notify();
}

/** LidSuspendMonitor Implement */

bool LidSuspendMonitor::Init()
{
    return true;
}

void LidSuspendMonitor::Cancel() {}

/** SwitchSuspendMonitor Implement */

bool SwitchSuspendMonitor::Init()
{
    return true;
}

void SwitchSuspendMonitor::Cancel() {}

/** TPCoverSuspendMonitor Implement */

bool TPCoverSuspendMonitor::Init()
{
#ifdef HAS_MULTIMODALINPUT_INPUT_PART
    if (TPCoverReleaseId_ >= 0) {
        return true;
    }
    std::shared_ptr<OHOS::MMI::KeyOption> keyOption = std::make_shared<OHOS::MMI::KeyOption>();
    std::set<int32_t> preKeys;
    keyOption->SetPreKeys(preKeys);
    keyOption->SetFinalKey(OHOS::MMI::KeyEvent::KEYCODE_SLEEP);
    keyOption->SetFinalKeyDownDuration(0);
    auto inputManager = InputManager::GetInstance();
    if (!inputManager) {
        POWER_HILOGE(FEATURE_SUSPEND, "TPCoverSuspendMonitorInit inputManager is null");
        return false;
    }
    TPCoverReleaseId_ = inputManager->SubscribeKeyEvent(
        keyOption, [this](std::shared_ptr<OHOS::MMI::KeyEvent> keyEvent) {
            POWER_HILOGI(FEATURE_SUSPEND, "[UL_POWER] Received TPCover event");
            this->Notify();
        });
    POWER_HILOGI(FEATURE_SUSPEND, "TPCoverReleaseId_=%{public}d", TPCoverReleaseId_);
    return TPCoverReleaseId_ >= 0 ? true : false;
#else
    return false;
#endif
}

void TPCoverSuspendMonitor::Cancel()
{
#ifdef HAS_MULTIMODALINPUT_INPUT_PART
    auto inputManager = InputManager::GetInstance();
    if (!inputManager) {
        POWER_HILOGE(FEATURE_SUSPEND, "TPCoverSuspendMonitorCancel inputManager is null");
        return;
    }
    if (TPCoverReleaseId_ >= 0) {
        POWER_HILOGI(FEATURE_SUSPEND, "UnsubscribeKeyEvent: TPCoverSuspendMonitor");
        inputManager->UnsubscribeKeyEvent(TPCoverReleaseId_);
        TPCoverReleaseId_ = -1;
    }
#endif
}
} // namespace PowerMgr
} // namespace OHOS