/*
 * Copyright (c) 2021-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 "power_state_machine.h"

#include <future>
#include <thread>
#include <algorithm>
#include <cinttypes>
#include <datetime_ex.h>
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
#include <hisysevent.h>
#endif
#include <ipc_skeleton.h>
#include "power_ext_intf_wrapper.h"
#include <power_hookmgr.h>
#ifdef HAS_HIVIEWDFX_HITRACE_PART
#include "hitrace_meter.h"
#endif
#include "power_mode_policy.h"
#include "power_mgr_factory.h"
#include "power_mgr_service.h"
#include "power_utils.h"
#include "setting_helper.h"
#include "system_suspend_controller.h"
#ifdef POWER_MANAGER_POWER_ENABLE_S4
#include "os_account_manager.h"
#include "parameters.h"
#endif
#ifdef MSDP_MOVEMENT_ENABLE
#include <dlfcn.h>
#endif
#include "screen_common_event_controller.h"
#include "screen_manager_lite.h"
#include "display_manager_lite.h"

namespace OHOS {
namespace PowerMgr {
namespace {
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
sptr<SettingObserver> g_displayOffTimeAcObserver;
sptr<SettingObserver> g_displayOffTimeDcObserver;
#else
sptr<SettingObserver> g_displayOffTimeObserver;
#endif
static int64_t g_beforeOverrideTime {-1};
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
constexpr int32_t DISPLAY_OFF = 0;
constexpr int32_t DISPLAY_ON = 2;
#endif
const std::string POWERMGR_STOPSERVICE = "persist.powermgr.stopservice";
constexpr uint32_t PRE_BRIGHT_AUTH_TIMER_DELAY_MS = 3000;
#ifdef POWER_MANAGER_POWER_ENABLE_S4
constexpr uint32_t PREPARE_HIBERNATE_INACTIVE_DELAY_US = 1500000;
constexpr uint32_t POST_HIBERNATE_CLEARMEM_DELAY_US = 2000000;
constexpr uint32_t HIBERNATE_DELAY_MS = 3500;
constexpr int32_t PREPARE_HIBERNATE_TIMEOUT_MS = 30000;
static int64_t g_preHibernateStart = 0;
std::atomic_bool g_prepareResult = true;
#endif
pid_t g_callSetForceTimingOutPid = 0;
pid_t g_callSetForceTimingOutUid = 0;
const std::string LID_STATUS_SCENE_NAME = "lid_status";
#ifdef POWER_MANAGER_REPORT_SCREENOFF_INVALID
constexpr int32_t SCREEN_OFF_ABNORMAL = 0;
constexpr int32_t SCREEN_OFF_INVALID = 1;
#endif
}
PowerStateMachine::PowerStateMachine(const wptr<PowerMgrService>& pms, const std::shared_ptr<FFRTTimer>& ffrtTimer)
    : pms_(pms), ffrtTimer_(ffrtTimer), currentState_(PowerState::UNKNOWN)
{
    POWER_HILOGD(FEATURE_POWER_STATE, "Instance start");
    // NOTICE Need get screen state when device startup,
    // rightnow we set screen is on as default
    mDeviceState_.screenState.lastOnTime = GetTickCount();
    mDeviceState_.screenState.lastOffTime = 0;
    mDeviceState_.lastWakeupEventTime = 0;
    mDeviceState_.lastRefreshActivityTime = 0;
    mDeviceState_.lastWakeupDeviceTime = 0;
    mDeviceState_.lastSuspendDeviceTime = 0;

    // init lock map which will block state transit
    std::vector<RunningLockType> awakeBlocker {};
    std::vector<RunningLockType> freezeBlocker {};
    std::vector<RunningLockType> inactiveBlocker {RunningLockType::RUNNINGLOCK_SCREEN};
    std::vector<RunningLockType> standByBlocker {};
    std::vector<RunningLockType> dozeBlocker {};
    std::vector<RunningLockType> sleepBlocker {
        RunningLockType::RUNNINGLOCK_COORDINATION
    };
    std::vector<RunningLockType> hibernateBlocker {};
    std::vector<RunningLockType> shutdownBlocker {};

    lockMap_.emplace(PowerState::AWAKE, std::make_shared<std::vector<RunningLockType>>(awakeBlocker));
    lockMap_.emplace(PowerState::FREEZE, std::make_shared<std::vector<RunningLockType>>(freezeBlocker));
    lockMap_.emplace(PowerState::INACTIVE, std::make_shared<std::vector<RunningLockType>>(inactiveBlocker));
    lockMap_.emplace(PowerState::STAND_BY, std::make_shared<std::vector<RunningLockType>>(standByBlocker));
    lockMap_.emplace(PowerState::DOZE, std::make_shared<std::vector<RunningLockType>>(dozeBlocker));
    lockMap_.emplace(PowerState::SLEEP, std::make_shared<std::vector<RunningLockType>>(sleepBlocker));
    lockMap_.emplace(PowerState::HIBERNATE, std::make_shared<std::vector<RunningLockType>>(hibernateBlocker));
    lockMap_.emplace(PowerState::SHUTDOWN, std::make_shared<std::vector<RunningLockType>>(shutdownBlocker));

    POWER_HILOGD(FEATURE_POWER_STATE, "Instance end");
}

PowerStateMachine::~PowerStateMachine()
{
    ffrtTimer_.reset();
}

bool PowerStateMachine::Init()
{
    POWER_HILOGD(FEATURE_POWER_STATE, "Start init");
    stateAction_ = PowerMgrFactory::GetDeviceStateAction();
    InitTransitMap();
    InitStateMap();
    InitSwitchAction();

    if (powerStateCBDeathRecipient_ == nullptr) {
        powerStateCBDeathRecipient_ = new PowerStateCallbackDeathRecipient();
    }
    activeTimeBeforeLongTimeDim_ =
        static_cast<int64_t>(system::GetIntParameter("const.power.active_time_before_long_time_dim", -1));
    POWER_HILOGD(FEATURE_POWER_STATE, "Init success");
    return true;
}

void PowerStateMachine::InitTransitMap()
{
#ifdef POWER_MANAGER_POWER_ENABLE_S4
    std::vector<PowerState> awake { PowerState::SLEEP };
    std::vector<PowerState> hibernate { PowerState::SLEEP };
#else
    std::vector<PowerState> awake { PowerState::SLEEP, PowerState::HIBERNATE };
#endif
    std::vector<PowerState> inactive { PowerState::DIM };
    std::vector<PowerState> dim { PowerState::SLEEP };
    std::vector<PowerState> sleep { PowerState::DIM };

    forbidMap_.emplace(PowerState::AWAKE, std::set<PowerState>(awake.begin(), awake.end()));
    forbidMap_.emplace(PowerState::INACTIVE, std::set<PowerState>(inactive.begin(), inactive.end()));
    forbidMap_.emplace(PowerState::DIM, std::set<PowerState>(dim.begin(), dim.end()));
    forbidMap_.emplace(PowerState::SLEEP, std::set<PowerState>(sleep.begin(), sleep.end()));
#ifdef POWER_MANAGER_POWER_ENABLE_S4
    forbidMap_.emplace(PowerState::HIBERNATE, std::set<PowerState>(hibernate.begin(), hibernate.end()));
#endif

    allowMapByReason_.insert({
        {
            StateChangeReason::STATE_CHANGE_REASON_REFRESH,
            {
                {PowerState::DIM, {PowerState::AWAKE}},
                {PowerState::AWAKE, {PowerState::AWAKE}}
            }
        },
        {
            StateChangeReason::STATE_CHANGE_REASON_TIMEOUT,
            {
                // allow AWAKE to INACTIVE without going to DIM for UTs to pass
                {PowerState::AWAKE, {PowerState::DIM, PowerState::INACTIVE}},
                {PowerState::DIM, {PowerState::INACTIVE}},
                {PowerState::INACTIVE, {PowerState::SLEEP}}
            }
        },
        {
            StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK,
            {
                {PowerState::DIM, {PowerState::INACTIVE}},
                // allow AWAKE to INACTIVE without going to DIM for UTs to pass
                {PowerState::AWAKE, {PowerState::INACTIVE}}
            }
        },
        {
            StateChangeReason::STATE_CHANGE_REASON_ROLLBACK_HIBERNATE,
            {
                {PowerState::AWAKE, {PowerState::INACTIVE}},
                {PowerState::INACTIVE, {PowerState::SLEEP}},
                {PowerState::HIBERNATE, {PowerState::INACTIVE}},
            }
        },
    });
}

#ifdef MSDP_MOVEMENT_ENABLE
static const char* MOVEMENT_STATE_CONFIG = "GetMovementState";
static const char* POWER_MANAGER_EXT_PATH = "libpower_manager_ext.z.so";
typedef bool(*FuncMovementState)();

bool PowerStateMachine::IsMovementStateOn()
{
    POWER_HILOGD(FEATURE_POWER_STATE, "Start to GetMovementState");
    void *stateHandler = dlopen(POWER_MANAGER_EXT_PATH, RTLD_LAZY | RTLD_NODELETE);
    if (stateHandler == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Dlopen GetMovementState failed, reason : %{public}s", dlerror());
        return false;
    }

    FuncMovementState MovementStateFlag = reinterpret_cast<FuncMovementState>(dlsym(stateHandler,
        MOVEMENT_STATE_CONFIG));
    if (MovementStateFlag == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "GetMovementState is null, reason : %{public}s", dlerror());
        dlclose(stateHandler);
        stateHandler = nullptr;
        return false;
    }
    bool ret = MovementStateFlag();
    dlclose(stateHandler);
    stateHandler = nullptr;
    return ret;
}
#endif

bool PowerStateMachine::CanTransitTo(PowerState from, PowerState to, StateChangeReason reason)
{
    bool isForbidden = forbidMap_.count(currentState_) && forbidMap_[currentState_].count(to);
    if (isForbidden) {
        return false;
    }
    // prevent the double click or pickup or usb plug to light up the screen
    // when calling or sporting or lid is close
    if ((reason == StateChangeReason::STATE_CHANGE_REASON_DOUBLE_CLICK ||
        reason == StateChangeReason::STATE_CHANGE_REASON_PICKUP ||
        reason == StateChangeReason::STATE_CHANGE_REASON_PLUG_CHANGE) && to == PowerState::AWAKE) {
#ifdef HAS_SENSORS_SENSOR_PART
        if (IsProximityClose()) {
            POWER_HILOGI(FEATURE_POWER_STATE, "Double-click or pickup or "
                "usb plug isn't allowed to wakeup device when proximity is close during calling.");
            StartSleepTimer(from);
            return false;
        }
        // prevent the pickup to light up the screen when lid is close
        if (PowerMgrService::isInLidMode_ == true && reason == StateChangeReason::STATE_CHANGE_REASON_PICKUP) {
            POWER_HILOGI(FEATURE_POWER_STATE, "Pickup isn't allowed to wakeup device when lid is close.");
            StartSleepTimer(from);
            return false;
        }
#endif
#ifdef MSDP_MOVEMENT_ENABLE
        if (IsMovementStateOn() && (reason == StateChangeReason::STATE_CHANGE_REASON_DOUBLE_CLICK ||
            reason == StateChangeReason::STATE_CHANGE_REASON_PICKUP)) {
            POWER_HILOGI(FEATURE_POWER_STATE,
                "Double-click or pickup isn't allowed to wakeup device when movement state is on.");
            StartSleepTimer(from);
            return false;
        }
#endif
    }
    if (reason == StateChangeReason::STATE_CHANGE_REASON_PROXIMITY && to == PowerState::INACTIVE &&
        !IsRunningLockEnabled(RunningLockType::RUNNINGLOCK_PROXIMITY_SCREEN_CONTROL)) {
        POWER_HILOGI(FEATURE_POWER_STATE, "this proximity task is invalidated, directly return");
        return false;
    }
    bool isAllowed = (!allowMapByReason_.count(reason) ||
        (allowMapByReason_[reason].count(currentState_) && allowMapByReason_[reason][currentState_].count(to)));
    return isAllowed;
}

void PowerStateMachine::StartSleepTimer(PowerState from)
{
    if (from == PowerState::SLEEP) {
        uint32_t delay = 0;
        POWER_HILOGI(FEATURE_POWER_STATE, "Double-click or pickup isn't allowed to wakeup device, SetAutoSuspend");
        SetAutoSuspend(SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION, delay);
    }
}

void PowerStateMachine::InitState()
{
    POWER_HILOGI(FEATURE_POWER_STATE, "Init power state");
    if (IsScreenOn() ||
        switchAction_->HandleSwitchAction(SwitchActionType::IS_SCREEN_ON) == SwitchActionRet::IS_SCREEN_ON) {
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::DISPLAY, "SCREEN_STATE",
            HiviewDFX::HiSysEvent::EventType::STATISTIC, "STATE", DISPLAY_ON);
#endif
        SetState(PowerState::AWAKE, StateChangeReason::STATE_CHANGE_REASON_INIT, true);
        Rosen::ScreenManagerLite::GetInstance().SyncScreenPowerState(Rosen::ScreenPowerState::POWER_ON);
    } else {
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::DISPLAY, "SCREEN_STATE",
            HiviewDFX::HiSysEvent::EventType::STATISTIC, "STATE", DISPLAY_OFF);
#endif
        SetState(PowerState::INACTIVE, StateChangeReason::STATE_CHANGE_REASON_INIT, true);
        Rosen::ScreenManagerLite::GetInstance().SyncScreenPowerState(Rosen::ScreenPowerState::POWER_OFF);
    }
}

void PowerStateMachine::InitSwitchAction()
{
    std::string foldType = system::GetParameter("const.window.foldscreen.type", "");
    if (foldType == "5,3,0,0") {
        SetSwitchAction(std::make_shared<DualScreenSwitchAction>());
        POWER_HILOGI(FEATURE_WAKEUP, "Switch action loaded from plugin");
    } else {
        SetSwitchAction(std::make_shared<ISwitchAction>());
        POWER_HILOGI(FEATURE_WAKEUP, "Using default switch action");
    }
}

void PowerStateMachine::EmplaceAwake()
{
    controllerMap_.emplace(PowerState::AWAKE,
        std::make_shared<StateController>(PowerState::AWAKE, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGD(FEATURE_POWER_STATE, "[UL_POWER] StateController_AWAKE lambda start, reason=%{public}s",
                PowerUtils::GetReasonTypeString(reason).c_str());
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
            HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER_UE, "SCREEN_ON",
                HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PNAMEID", "PowerManager", "PVERSIONID", "1.0",
                "REASON", PowerUtils::GetReasonTypeString(reason).c_str());
            HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SCREEN_ON",
                HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "REASON", PowerUtils::GetReasonTypeString(reason).c_str());
#endif
            mDeviceState_.screenState.lastOnTime = GetTickCount();
            auto targetState = DisplayState::DISPLAY_ON;
            if (reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) {
                if (isDozeEnabled_) {
                    targetState = DisplayState::DISPLAY_DOZE;
                } else {
                    targetState = DisplayState::DISPLAY_OFF;
                }
            }
            uint32_t ret = this->stateAction_->SetDisplayState(targetState, reason);
            if (ret != ActionResult::SUCCESS) {
                POWER_HILOGE(FEATURE_POWER_STATE, "Failed to go to AWAKE, display error, ret: %{public}u", ret);
                return TransitResult::DISPLAY_ON_ERR;
            }
#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
            if (reason == StateChangeReason::STATE_CHANGE_REASON_SWITCH && IsSwitchOpen()) {
                SetInternalScreenDisplayState(DisplayState::DISPLAY_ON, reason);
            }
#endif
            if (reason != StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT) {
                ResetInactiveTimer();
            }
            SystemSuspendController::GetInstance().DisallowAutoSleep();
            SystemSuspendController::GetInstance().Wakeup();
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceFreeze()
{
    controllerMap_.emplace(PowerState::FREEZE,
        std::make_shared<StateController>(PowerState::FREEZE, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_FREEZE lambda start");
            // Subsequent added functions
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceInactive()
{
    controllerMap_.emplace(PowerState::INACTIVE,
        std::make_shared<StateController>(PowerState::INACTIVE, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGD(FEATURE_POWER_STATE, "[UL_POWER] StateController_INACTIVE lambda start");
#ifdef POWER_MANAGER_TAKEOVER_SUSPEND
            TransitResult result = TakeOverSuspendAction(reason);
            if (result != TransitResult::SUCCESS) {
                return result;
            }
#endif
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
            HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER_UE, "SCREEN_OFF",
                HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PNAMEID", "PowerManager", "PVERSIONID", "1.0",
                "REASON", PowerUtils::GetReasonTypeString(reason).c_str());
#endif
            mDeviceState_.screenState.lastOffTime = GetTickCount();
            DisplayState state = DisplayState::DISPLAY_OFF;
            if (reason != StateChangeReason::STATE_CHANGE_REASON_SWITCH_SENSORHUB
                && isDozeEnabled_.load(std::memory_order_relaxed)) {
                state = DisplayState::DISPLAY_DOZE;
            }
#ifdef POWER_MANAGER_REPORT_SCREENOFF_INVALID
            ReportScreenOffInvalidEvent(reason);
#endif
            uint32_t ret = this->stateAction_->SetDisplayState(state, reason);
            if (ret != ActionResult::SUCCESS) {
                POWER_HILOGE(FEATURE_POWER_STATE, "Failed to go to INACTIVE, display error, ret: %{public}u", ret);
                return TransitResult::DISPLAY_OFF_ERR;
            }
            CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_TIMEOUT_MSG);
            CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG);
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceStandBy()
{
    controllerMap_.emplace(PowerState::STAND_BY,
        std::make_shared<StateController>(PowerState::STAND_BY, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_STAND_BY lambda start");
            mDeviceState_.screenState.lastOffTime = GetTickCount();
            // Subsequent added functions
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceDoze()
{
    controllerMap_.emplace(PowerState::DOZE,
        std::make_shared<StateController>(PowerState::DOZE, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_DOZE lambda start");
            mDeviceState_.screenState.lastOffTime = GetTickCount();
            // Subsequent added functions
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceSleep()
{
    controllerMap_.emplace(PowerState::SLEEP,
        std::make_shared<StateController>(PowerState::SLEEP, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_SLEEP lambda start");
            SystemSuspendController::GetInstance().AllowAutoSleep();
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceHibernate()
{
    controllerMap_.emplace(PowerState::HIBERNATE,
        std::make_shared<StateController>(PowerState::HIBERNATE, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_HIBERNATE lambda start");
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceShutdown()
{
    controllerMap_.emplace(PowerState::SHUTDOWN,
        std::make_shared<StateController>(PowerState::SHUTDOWN, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGI(FEATURE_POWER_STATE, "StateController_SHUTDOWN lambda start");
            // Subsequent added functions
            return TransitResult::SUCCESS;
        }));
}

void PowerStateMachine::EmplaceDim()
{
    controllerMap_.emplace(PowerState::DIM,
        std::make_shared<StateController>(PowerState::DIM, shared_from_this(), [this](StateChangeReason reason) {
            POWER_HILOGD(FEATURE_POWER_STATE, "[UL_POWER] StateController_DIM lambda start");
            if (GetDisplayOffTime() < 0) {
                POWER_HILOGD(FEATURE_ACTIVITY, "Auto display off is disabled");
                return TransitResult::OTHER_ERR;
            }
            int64_t dimTime = GetDimTime(GetDisplayOffTime());
            if (reason == StateChangeReason::STATE_CHANGE_REASON_COORDINATION) {
                dimTime = COORDINATED_STATE_SCREEN_OFF_TIME_MS;
            }
            uint32_t ret = stateAction_->SetDisplayState(DisplayState::DISPLAY_DIM, reason);
            if (ret != ActionResult::SUCCESS) {
                // failed but not return, still need to set screen off
                POWER_HILOGE(FEATURE_POWER_STATE, "Failed to go to DIM, display error, ret: %{public}u", ret);
            }
#ifdef POWER_MANAGER_REPORT_SCREENOFF_INVALID
            ReportAbnormalScreenOffEvent(reason);
#endif
            CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_TIMEOUT_MSG);
            CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG);
            // Set a timer without checking runninglock, but the actual timeout event can still be blocked.
            // Theoretically, this timer is always cancelable before the current task is finished.
            SetDelayTimer(dimTime, PowerStateMachine::CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG);
            // in case a refresh action occurs, change display state back to on
            if (settingStateFlag_.load() ==
                static_cast<int64_t>(SettingStateFlag::StateFlag::SETTING_DIM_INTERRUPTED)) {
                stateAction_->SetDisplayState(DisplayState::DISPLAY_ON, StateChangeReason::STATE_CHANGE_REASON_REFRESH);
                ResetInactiveTimer();
                POWER_HILOGW(FEATURE_POWER_STATE, "Setting DIM interrupted!");
                return TransitResult::OTHER_ERR;
            }
            return ret == ActionResult::SUCCESS ? TransitResult::SUCCESS : TransitResult::OTHER_ERR;
        }));
}

void PowerStateMachine::InitStateMap()
{
    EmplaceAwake();
    EmplaceFreeze();
    EmplaceInactive();
    EmplaceStandBy();
    EmplaceDoze();
    EmplaceSleep();
    EmplaceHibernate();
    EmplaceShutdown();
    EmplaceDim();
}

void PowerStateMachine::onSuspend()
{
    POWER_HILOGI(FEATURE_SUSPEND, "System is suspending");
}

void PowerStateMachine::onWakeup()
{
    POWER_HILOGI(FEATURE_WAKEUP, "System is awaking");
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        return;
    }
    FFRTTask task = [&pms] {
        pms->GetPowerStateMachine()->HandleSystemWakeup();
    };
}

void PowerStateMachine::SuspendDeviceInner(
    pid_t pid, int64_t callTimeMs, SuspendDeviceType type, bool suspendImmed, bool ignoreScreenState)
{
#ifdef HAS_HIVIEWDFX_HITRACE_PART
    HitraceScopedEx powerHitrace(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_POWER, "SuspendDevice");
#endif
    if (type > SuspendDeviceType::SUSPEND_DEVICE_REASON_MAX) {
        POWER_HILOGW(FEATURE_SUSPEND, "Invalid type: %{public}d", type);
        return;
    }
    // Check the screen state
    if (!ignoreScreenState) {
        if (stateAction_ != nullptr) {
            stateAction_->Suspend(
                callTimeMs, type, suspendImmed ? SUSPEND_DEVICE_IMMEDIATELY : SUSPEND_DEVICE_NEED_DOZE);
        }
        mDeviceState_.lastSuspendDeviceTime = callTimeMs;
        POWER_HILOGD(FEATURE_SUSPEND, "Suspend device success");
    } else {
        POWER_HILOGD(FEATURE_SUSPEND, "Do not suspend device, screen state is ignored");
    }
#ifdef POWER_MANAGER_TV_DREAMING
    if (type == SuspendDeviceType::SUSPEND_DEVICE_START_DREAM) {
        SetDreamingState(GetReasonBySuspendType(type));
        return;
    }
#endif
    if (SetState(PowerState::INACTIVE, GetReasonBySuspendType(type), true)) {
        uint32_t delay = 0;
        SetAutoSuspend(type, delay);
    }
    POWER_HILOGD(FEATURE_SUSPEND, "Suspend device finish");
}

bool PowerStateMachine::SetDreamingState(StateChangeReason reason)
{
#ifdef POWER_MANAGER_TV_DREAMING
    Rosen::PowerStateChangeReason dispReason = PowerUtils::GetDmsReasonByPowerReason(reason);
    if (reason == StateChangeReason::STATE_CHANGE_REASON_START_DREAM) {
        bool isSuccess = Rosen::DisplayManagerLite::GetInstance().SuspendBegin(dispReason);
        POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER] start dreaming success=%{public}d", isSuccess);
        return isSuccess;
    } else if (reason == StateChangeReason::STATE_CHANGE_REASON_END_DREAM) {
        bool isSuccess = Rosen::DisplayManagerLite::GetInstance().WakeUpBegin(dispReason);
        POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER] end dreaming success=%{public}d", isSuccess);
        return isSuccess;
    }
#endif
    return false;
}

bool PowerStateMachine::IsPreBrightAuthReason(StateChangeReason reason)
{
    bool ret = false;
    switch (reason) {
        case StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_SUCCESS:
            ret = true;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_ON:
            ret = true;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF:
            ret = true;
            break;
        default:
            break;
    }
    return ret;
}

bool PowerStateMachine::IsPreBrightWakeUp(WakeupDeviceType type)
{
    bool ret = false;
    switch (type) {
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT:
            ret = true;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_SUCCESS:
            ret = true;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_ON:
            ret = true;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF:
            ret = true;
            break;
        default:
            break;
    }
    return ret;
}

void PowerStateMachine::HandlePreBrightWakeUp(int64_t callTimeMs, WakeupDeviceType type, const std::string& details,
    const std::string& pkgName, bool timeoutTriggered)
{
    POWER_HILOGD(FEATURE_WAKEUP, "This wakeup event is trigged by %{public}s.", details.c_str());

    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    auto suspendController = pms->GetSuspendController();
    if (suspendController != nullptr) {
        suspendController->StopSleep();
    } else {
        POWER_HILOGI(FEATURE_WAKEUP, "suspendController is nullptr, can't stop sleep ffrt task");
    }
    if (stateAction_ != nullptr) {
        stateAction_->Wakeup(callTimeMs, type, details, pkgName);
    }
    mDeviceState_.lastWakeupDeviceTime = callTimeMs;

    StateChangeReason reason = GetReasonByWakeType(type);
    if (!timeoutTriggered && IsPreBrightAuthReason(reason)) {
        POWER_HILOGI(FEATURE_WAKEUP, "Cancel pre-bright-auth timer, rason=%{public}s",
            PowerUtils::GetReasonTypeString(reason).c_str());
        CancelDelayTimer(PowerStateMachine::CHECK_PRE_BRIGHT_AUTH_TIMEOUT_MSG);
    }
    SetState(PowerState::AWAKE, reason, true);

    switch (type) {
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT: {
            break;
        }
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_SUCCESS: // fall through
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_ON:
            if (suspendController != nullptr) {
                POWER_HILOGD(FEATURE_WAKEUP, "HandlePreBrightWakeUp. TriggerSyncSleepCallback start.");
                suspendController->TriggerSyncSleepCallback(true);
            } else {
                POWER_HILOGI(FEATURE_WAKEUP, "HandlePreBrightWakeUp. suspendController is nullptr");
            }
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF:
            if (suspendController != nullptr) {
                suspendController->StartSleepTimer(
                    SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION,
                    static_cast<uint32_t>(SuspendAction::ACTION_AUTO_SUSPEND), 0);
            } else {
                POWER_HILOGI(FEATURE_WAKEUP, "suspendController is nullptr, can't restore sleep ffrt task");
            }
            break;
        default:
            break;
    }

    return;
}

bool PowerStateMachine::IsWakeupDeviceSkip()
{
    bool ret = false;
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    ret = ret || !IsSwitchOpen();
#ifdef POWER_MANAGER_POWER_ENABLE_S4
    ret = ret || IsHibernating();
#endif
    if (pms && pms->IsLidCheckEnable()) {
        ret = ret || PowerMgrService::isInLidMode_;
    }
    if (ret && switchAction_ != nullptr) {
        auto actionRet = switchAction_->HandleSwitchAction(SwitchActionType::WAKEUP_IN_CLOSED_STATE);
        ret = actionRet == SwitchActionRet::DEFAULT;
    }
    return ret;
}

void PowerStateMachine::WakeupDeviceInner(
    pid_t pid, int64_t callTimeMs, WakeupDeviceType type, const std::string& details, const std::string& pkgName)
{
#ifdef HAS_HIVIEWDFX_HITRACE_PART
    HitraceScopedEx powerHitrace(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_POWER, "WakeupDevice");
#endif
    if (type > WakeupDeviceType::WAKEUP_DEVICE_MAX) {
        POWER_HILOGW(FEATURE_WAKEUP, "Invalid type: %{public}d", type);
        return;
    }

    if (IsWakeupDeviceSkip()) {
        POWER_HILOGI(FEATURE_WAKEUP, "Switch is closed or hibernating, wakeup device skip.");
        return;
    }

    if (type == WakeupDeviceType::WAKEUP_DEVICE_APPLICATION) {
        type = PowerUtils::ParseWakeupDeviceType(details);
    }

    if (IsPreBrightWakeUp(type)) {
        HandlePreBrightWakeUp(callTimeMs, type, details, pkgName);
        return;
    }

    // Call legacy wakeup, Check the screen state
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();

#ifdef POWER_MANAGER_TV_DREAMING
    if (details == "start_dream") {
        SetDreamingState(StateChangeReason::STATE_CHANGE_REASON_START_DREAM);
        return;
    }
    if (type == WakeupDeviceType::WAKEUP_DEVICE_END_DREAM) {
        SetDreamingState(GetReasonByWakeType(type));
        return;
    }
#endif

    auto suspendController = pms->GetSuspendController();
    if (suspendController != nullptr) {
        POWER_HILOGI(FEATURE_WAKEUP, "Stop sleep ffrt task");
        suspendController->StopSleep();
    }

    if (stateAction_ != nullptr) {
        stateAction_->Wakeup(callTimeMs, type, details, pkgName);
    }
    mDeviceState_.lastWakeupDeviceTime = callTimeMs;

    SetState(PowerState::AWAKE, GetReasonByWakeType(type), true);

    if (suspendController != nullptr) {
        POWER_HILOGD(FEATURE_WAKEUP, "WakeupDeviceInner. TriggerSyncSleepCallback start.");
        suspendController->TriggerSyncSleepCallback(true);
    } else {
        POWER_HILOGI(FEATURE_WAKEUP, "WakeupDeviceInner. suspendController is nullptr");
    }

    POWER_HILOGD(FEATURE_WAKEUP, "Wakeup device finish");
}

void PowerStateMachine::RefreshActivityInner(
    pid_t pid, int64_t callTimeMs, UserActivityType type, bool needChangeBacklight)
{
    if (type > UserActivityType::USER_ACTIVITY_TYPE_MAX) {
        POWER_HILOGW(FEATURE_ACTIVITY, "Invalid type: %{public}d", type);
        return;
    }
    // Check the screen state
    if (IsScreenOn() && !IsSettingState(PowerState::INACTIVE)) {
        if (stateAction_ != nullptr) {
            stateAction_->RefreshActivity(callTimeMs, type,
                needChangeBacklight ? REFRESH_ACTIVITY_NEED_CHANGE_LIGHTS : REFRESH_ACTIVITY_NO_CHANGE_LIGHTS);
            mDeviceState_.screenState.lastOnTime = GetTickCount();
        }
        if (GetState() == PowerState::DIM || IsSettingState(PowerState::DIM)) {
            // Inactive to Awake will be blocked for this reason in CanTransitTo()
            SetState(PowerState::AWAKE, StateChangeReason::STATE_CHANGE_REASON_REFRESH, true);
        } else {
            // There is a small chance that the last "if" statement occurs before the (already started) ffrt task
            // is actually trying to set DIM state.
            // In that case we may still (not guaranteed) interrupt it.
            ResetInactiveTimer(false);
        }
    } else {
        POWER_HILOGD(FEATURE_ACTIVITY, "Ignore refresh activity, screen is off");
    }
}

bool PowerStateMachine::CheckRefreshTime()
{
    // The minimum refreshactivity interval is 100ms!!
    int64_t now = GetTickCount();
    if ((mDeviceState_.lastRefreshActivityTime + MIN_TIME_MS_BETWEEN_USERACTIVITIES) > now) {
        return true;
    }
    mDeviceState_.lastRefreshActivityTime = now;
    return false;
}

bool PowerStateMachine::OverrideScreenOffTimeInner(int64_t timeout)
{
    if (!isScreenOffTimeOverride_) {
        int64_t beforeOverrideTime = this->GetDisplayOffTime();
        isScreenOffTimeOverride_ = true;
        g_beforeOverrideTime = beforeOverrideTime;
    }
    this->SetDisplayOffTime(timeout, false);
    POWER_HILOGD(COMP_SVC, "Override screenOffTime finish");
    return true;
}

bool PowerStateMachine::RestoreScreenOffTimeInner()
{
    if (!isScreenOffTimeOverride_) {
        POWER_HILOGD(COMP_SVC, "RestoreScreenOffTime is not override, no need to restore");
        return false;
    }
    this->SetDisplayOffTime(g_beforeOverrideTime, false);
    isScreenOffTimeOverride_ = false;
    POWER_HILOGD(COMP_SVC, "Restore screenOffTime finish");
    return true;
}

bool PowerStateMachine::ForceSuspendDeviceInner(pid_t pid, int64_t callTimeMs)
{
#ifdef POWER_MANAGER_TAKEOVER_SUSPEND
    auto setStateRet = SetState(
        PowerState::INACTIVE, GetReasonBySuspendType(SuspendDeviceType::SUSPEND_DEVICE_REASON_FORCE_SUSPEND), true);
    RETURN_IF_WITH_RET(!setStateRet, true);
#else
    SetState(
        PowerState::INACTIVE, GetReasonBySuspendType(SuspendDeviceType::SUSPEND_DEVICE_REASON_FORCE_SUSPEND), true);
#endif
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    auto suspendController = pms->GetSuspendController();
    if (suspendController != nullptr) {
        POWER_HILOGI(FEATURE_SUSPEND, "ForceSuspendDeviceInner StartSleepTimer start.");
        suspendController->StartSleepTimer(
            SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION,
            static_cast<uint32_t>(SuspendAction::ACTION_FORCE_SUSPEND), 0);
    }

    POWER_HILOGI(FEATURE_SUSPEND, "Force suspend finish");
    return true;
}

#ifdef POWER_MANAGER_POWER_ENABLE_S4
void PowerStateMachine::DelayForHibernateInactive(bool clearMemory)
{
    if (clearMemory) {
        usleep(PREPARE_HIBERNATE_INACTIVE_DELAY_US);
    }
}

bool PowerStateMachine::ActivateDefaultAccount()
{
    POWER_HILOGI(FEATURE_SUSPEND, "Hibernate account deactivate begin.");
    if (AccountSA::OsAccountManager::DeactivateAllOsAccounts(false) != ERR_OK) {
        POWER_HILOGE(FEATURE_SUSPEND, "deactivate all os accounts failed.");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        ReportHibernatePrepareFailed(HibernatePrepareFailedReason::HIBERNATE_PREPARE_DEACTIVATE_ACCOUNTS_FAILED);
#endif
        return false;
    }
    int32_t id = 0;
    if (AccountSA::OsAccountManager::GetDefaultActivatedOsAccount(id) != ERR_OK) {
        POWER_HILOGE(FEATURE_SUSPEND, "get default activated os account failed.");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        ReportHibernatePrepareFailed(HibernatePrepareFailedReason::HIBERNATE_PREPARE_GET_DEFAULT_ACCOUNT_FAILED);
#endif
        return false;
    }
    if (AccountSA::OsAccountManager::ActivateOsAccount(id) != ERR_OK) {
        POWER_HILOGE(FEATURE_SUSPEND, "activate os account failed.");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        ReportHibernatePrepareFailed(HibernatePrepareFailedReason::HIBERNATE_PREPARE_ACTIVATE_DEFAULT_ACCOUNT_FAILED);
#endif
        return false;
    }
    POWER_HILOGI(FEATURE_SUSPEND, "Hibernate account deactivate end.");
    return true;
}

bool PowerStateMachine::PrepareHibernate(bool clearMemory)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    auto hibernateController = pms->GetHibernateController();
    if (hibernateController == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "hibernateController is nullptr.");
        return false;
    }
    SystemSuspendController::GetInstance().Wakeup();
    bool ret = true;
    DelayForHibernateInactive(clearMemory);
    if (!SetState(PowerState::INACTIVE, StateChangeReason::STATE_CHANGE_REASON_HIBERNATE, true)) {
        POWER_HILOGE(FEATURE_POWER_STATE, "failed to set state to inactive.");
    }

    g_preHibernateStart = GetTickCount();
    if (clearMemory) {
        auto hookMgr = GetPowerHookMgr();
        HookMgrExecute(hookMgr, static_cast<int32_t>(PowerHookStage::POWER_PRE_SWITCH_ACCOUNT), nullptr, nullptr);
        ret = ActivateDefaultAccount();
        if (ret == false) {
            return ret;
        }

        if (!OHOS::system::SetParameter(POWERMGR_STOPSERVICE.c_str(), "true")) {
            POWER_HILOGE(FEATURE_SUSPEND, "set parameter POWERMGR_STOPSERVICE true failed.");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
            ReportHibernatePrepareFailed(
                HibernatePrepareFailedReason::HIBERNATE_PREPARE_SET_POWERMGR_STOPSERVICE_FAILED);
#endif
            return false;
        }
        HookMgrExecute(hookMgr, static_cast<int32_t>(PowerHookStage::POWER_POST_SWITCH_ACCOUNT), nullptr, nullptr);
    }
    hibernateController->PreHibernate();
    POWER_HILOGI(FEATURE_SUSPEND, "Hibernate sync callback end.");

    if (!SetState(PowerState::HIBERNATE, StateChangeReason::STATE_CHANGE_REASON_SYSTEM, true)) {
        POWER_HILOGE(FEATURE_POWER_STATE, "failed to set state to hibernate.");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        ReportHibernatePrepareFailed(HibernatePrepareFailedReason::HIBERNATE_PREPARE_SET_STATE_HIBERNATE_FAILED);
#endif
        ret = false;
    }
    if (ret && clearMemory) {
        usleep(POST_HIBERNATE_CLEARMEM_DELAY_US);
    }
    return ret;
}

bool PowerStateMachine::PrepareHibernateWithTimeout(bool clearMemory)
{
    auto prepareCallback = [=]() {
        g_prepareResult = PrepareHibernate(clearMemory);
    };

    std::packaged_task<void()> callbackTask(prepareCallback);
    std::future<void> fut = callbackTask.get_future();
    std::make_unique<std::thread>(std::move(callbackTask))->detach();

    POWER_HILOGI(FEATURE_SUSPEND, "Waiting for the prepare hibernate execution complete...");
    std::future_status status = fut.wait_for(std::chrono::milliseconds(PREPARE_HIBERNATE_TIMEOUT_MS));
    if (status == std::future_status::timeout) {
        POWER_HILOGE(FEATURE_SUSPEND, "Prepare hibernate execution timeout");
        g_prepareResult = false;
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
        ReportHibernatePrepareFailed(HibernatePrepareFailedReason::HIBERNATE_PREPARE_TIMEOUT);
#endif
    }
    bool prepareResult = g_prepareResult.load(); // avoid g_prepareResult changed after timeout
    POWER_HILOGI(
        FEATURE_SUSPEND, "Prepare hibernate execution is complete, prepareResult: %{public}d", prepareResult);
    return prepareResult;
}

uint32_t PowerStateMachine::GetPreHibernateDelay()
{
    int64_t preHibernateEnd = GetTickCount();
    uint32_t preHibernateDelay = static_cast<uint32_t>(preHibernateEnd - g_preHibernateStart);
    preHibernateDelay = preHibernateDelay > HIBERNATE_DELAY_MS ? 0 : HIBERNATE_DELAY_MS - preHibernateDelay;
    POWER_HILOGI(FEATURE_SUSPEND, "preHibernateDelay = %{public}u", preHibernateDelay);
    return preHibernateDelay;
}

void PowerStateMachine::RestoreHibernate(bool clearMemory, HibernateStatus status,
    const std::shared_ptr<HibernateController>& hibernateController, const std::shared_ptr<PowerMgrNotify>& notify)
{
    // hibernateController and notify already judge empty
    bool hibernateRes = (status == HibernateStatus::HIBERNATE_SUCCESS);
    hibernating_ = false;

    if (notify) {
        notify->PublishExitHibernateEvent(GetTickCount(), clearMemory);
    }

    if (!SetState(PowerState::AWAKE, StateChangeReason::STATE_CHANGE_REASON_SYSTEM, true)) {
        POWER_HILOGE(FEATURE_POWER_STATE, "failed to set state to awake when hibernate.");
    }
    if (clearMemory) {
        if (!OHOS::system::SetParameter(POWERMGR_STOPSERVICE.c_str(), "false")) {
            POWER_HILOGE(FEATURE_SUSPEND, "set parameter POWERMGR_STOPSERVICE false failed.");
        }
    }
    PowerExtIntfWrapper::Instance().OnHibernateEnd(hibernateRes);
    hibernateController->PostHibernate(hibernateRes);
}

void PowerStateMachine::RollbackHibernate(
    PowerState originalState, bool clearMemory, bool needShutdown, const sptr<PowerMgrService>& pms)
{
    bool isSwitchOpen = IsSwitchOpen();
    POWER_HILOGI(FEATURE_SUSPEND,
        "Try to rollback hibernate, originalPowerState=%{public}d, clearMemory=%{public}d, needShutdown=%{public}d, "
        "isSwitchOpen=%{public}d",
        originalState, clearMemory, needShutdown, isSwitchOpen);
    hibernating_ = false;
    if (needShutdown) {
        // Ready to shutdown, so no need to publish common event and run PostHibernate
        pms->ShutDownDevice("HibernateFail");
        return;
    }
    if (pms->GetPowerMgrNotify() != nullptr) {
        pms->GetPowerMgrNotify()->PublishExitHibernateEvent(GetTickCount(), clearMemory);
    }
    if (pms->GetHibernateController() != nullptr) {
        pms->GetHibernateController()->PostHibernate(false);
    }
    SetState(PowerState::INACTIVE, StateChangeReason::STATE_CHANGE_REASON_ROLLBACK_HIBERNATE, true);
    if (originalState == PowerState::SLEEP) {
        if (!isSwitchOpen) {
            pms->SetSuspendTag("ulsr");
        }
        auto suspendController = pms->GetSuspendController();
        if (suspendController != nullptr) {
            suspendController->StartSleepTimer(SuspendDeviceType::SUSPEND_DEVICE_ROLLBACK_HIBERNATE,
                static_cast<uint32_t>(SuspendAction::ACTION_AUTO_SUSPEND), 0);
        }
    }
}

bool PowerStateMachine::HibernateInner(bool clearMemory, const std::string& reason)
{
    POWER_HILOGI(FEATURE_POWER_STATE, "HibernateInner begin.");
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "PowerMgr service is nullptr");
        return false;
    }
    auto shutdownController = pms->GetShutdownController();
    auto hibernateController = pms->GetHibernateController();
    auto notify = pms->GetPowerMgrNotify();
    if (shutdownController == nullptr || hibernateController == nullptr || notify == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "shutdown controller or hibernate controller or notify is nullptr.");
        return false;
    }

    if (clearMemory) {
        // do takeover only when user presses "shutdown" menu
        bool takenOver = shutdownController->TriggerTakeOverHibernateCallback(TakeOverInfo("hibernate", clearMemory));
        if (takenOver) {
            POWER_HILOGE(FEATURE_SUSPEND, "Hibernating is taken over by OnTakeOverHibernate callback");
            return true;
        }
    }
    if (hibernating_) {
        POWER_HILOGE(FEATURE_SUSPEND, "the device is hibernating, please try again later.");
        return false;
    }

    hibernating_ = true;
    PowerState originalState = GetState();
    bool needShutdown = clearMemory || reason == "LowCapacity";
    notify->PublishEnterHibernateEvent(GetTickCount(), clearMemory);

    bool ret = PrepareHibernateWithTimeout(clearMemory);
    if (!ret) {
        POWER_HILOGE(FEATURE_SUSPEND, "prepare hibernate failed, start to rollback");
        RollbackHibernate(originalState, clearMemory, needShutdown, pms);
        return true;
    }
    HibernateStatus status = hibernateController->Hibernate(clearMemory);
    if (status != HibernateStatus::HIBERNATE_SUCCESS) {
        POWER_HILOGE(FEATURE_SUSPEND, "do hibernate failed, start to rollback");
        RollbackHibernate(originalState, clearMemory, needShutdown, pms);
        return true;
    }
    SystemSuspendController::GetInstance().Wakeup(); // stop suspend loop
    RestoreHibernate(clearMemory, status, hibernateController, notify);
    POWER_HILOGI(FEATURE_SUSPEND, "HibernateInner end.");
    return true;
}
#endif

bool PowerStateMachine::IsScreenOn(bool needPrintLog)
{
#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
    bool isScreenOn {false};
    // When there's external screen, the original way to get screen state is inaccurate,
    // so use PowerState instead
    if (GetExternalScreenNumber() > 0) {
        PowerState powerState = GetState();
        isScreenOn = (powerState == PowerState::AWAKE) || (powerState == PowerState::DIM);
    } else {
        DisplayState displayState = stateAction_->GetDisplayState();
        isScreenOn = (displayState == DisplayState::DISPLAY_ON) || (displayState == DisplayState::DISPLAY_DIM);
    }
#else
    DisplayState state = stateAction_->GetDisplayState();
    bool isScreenOn = (state == DisplayState::DISPLAY_ON) || (state == DisplayState::DISPLAY_DIM);
#endif

    if (needPrintLog) {
        POWER_HILOGD(FEATURE_POWER_STATE, "Current screen is %{public}s", isScreenOn ? "ON" : "OFF");
    }
    return isScreenOn;
}

bool PowerStateMachine::IsScreenOnAcqLock()
{
    std::lock_guard<ffrt::mutex> lock(stateMutex_);
    DisplayState state = stateAction_->GetDisplayState();
    bool isScreenOn = (state == DisplayState::DISPLAY_ON) || (state == DisplayState::DISPLAY_DIM);
    return isScreenOn;
}

bool PowerStateMachine::IsFoldScreenOn()
{
    POWER_HILOGI(FEATURE_POWER_STATE,
        "IsFoldScreenOn settingOnStateFlag_ is %{public}d and settingOffStateFlag_ is %{public}d",
        settingOnStateFlag_.load(), settingOffStateFlag_.load());

    if (settingOnStateFlag_ == true) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Current fold screen is going on");
        return true;
    }
    if (settingOffStateFlag_ == true) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Current fold screen is going off");
        return false;
    }
    DisplayState state = stateAction_->GetDisplayState();
    if (state == DisplayState::DISPLAY_ON || state == DisplayState::DISPLAY_DIM) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Current fold screen is on or going on");
        return true;
    }
    POWER_HILOGI(FEATURE_POWER_STATE, "Current fold screen state is off, state: %{public}u", state);
    return false;
}

bool PowerStateMachine::IsCollaborationScreenOn()
{
    return isAwakeNotified_.load(std::memory_order_relaxed);
}

void PowerStateMachine::ReceiveScreenEvent(bool isScreenOn)
{
    POWER_HILOGD(FEATURE_POWER_STATE, "Enter");
    std::lock_guard lock(mutex_);
    auto prestate = mDeviceState_.screenState.state;
    if (isScreenOn) {
        mDeviceState_.screenState.lastOnTime = GetTickCount();
    } else {
        mDeviceState_.screenState.lastOffTime = GetTickCount();
    }
    if (prestate != mDeviceState_.screenState.state) {
        NotifyPowerStateChanged(isScreenOn ? PowerState::AWAKE : PowerState::INACTIVE);
    }
}

void PowerStateMachine::RegisterPowerStateCallback(const sptr<IPowerStateCallback>& callback, bool isSync)
{
    std::lock_guard lock(mutex_);
    RETURN_IF(callback == nullptr);
    auto object = callback->AsObject();
    RETURN_IF(object == nullptr);

    bool result = false;
    if (isSync) {
        auto retIt = syncPowerStateListeners_.insert(callback);
        result = retIt.second;
        POWER_HILOGD(FEATURE_POWER_STATE, "sync listeners.size = %{public}d, insertOk = %{public}d",
            static_cast<unsigned int>(syncPowerStateListeners_.size()), retIt.second);
    } else {
        auto retIt = asyncPowerStateListeners_.insert(callback);
        result = retIt.second;
        POWER_HILOGD(FEATURE_POWER_STATE, "async listeners.size = %{public}d, insertOk = %{public}d",
            static_cast<unsigned int>(asyncPowerStateListeners_.size()), retIt.second);
    }
    if (result) {
        object->AddDeathRecipient(powerStateCBDeathRecipient_);
    }
    pid_t pid = IPCSkeleton::GetCallingPid();
    auto uid = IPCSkeleton::GetCallingUid();
    cachedRegister_.emplace(callback, std::make_pair(pid, uid));
}

void PowerStateMachine::UnRegisterPowerStateCallback(const sptr<IPowerStateCallback>& callback)
{
    std::lock_guard lock(mutex_);
    RETURN_IF(callback == nullptr);
    auto object = callback->AsObject();
    RETURN_IF(object == nullptr);
    size_t eraseNum = 0;
    if (syncPowerStateListeners_.find(callback) != syncPowerStateListeners_.end()) {
        eraseNum = syncPowerStateListeners_.erase(callback);
        if (eraseNum != 0) {
            object->RemoveDeathRecipient(powerStateCBDeathRecipient_);
        }
        POWER_HILOGD(FEATURE_POWER_STATE, "sync listeners.size = %{public}d, eraseNum = %{public}zu",
            static_cast<unsigned int>(syncPowerStateListeners_.size()), eraseNum);
    } else {
        eraseNum = asyncPowerStateListeners_.erase(callback);
        if (eraseNum != 0) {
            object->RemoveDeathRecipient(powerStateCBDeathRecipient_);
        }
        POWER_HILOGD(FEATURE_POWER_STATE, "async listeners.size = %{public}d, eraseNum = %{public}zu",
            static_cast<unsigned int>(asyncPowerStateListeners_.size()), eraseNum);
    }
    if (cachedRegister_.find(callback) != cachedRegister_.end()) {
        cachedRegister_.erase(callback);
    }
}

void PowerStateMachine::EnableMock(IDeviceStateAction* mockAction)
{
    std::lock_guard lock(mutex_);
    displayOffTime_ = DEFAULT_DISPLAY_OFF_TIME_MS;
    sleepTime_ = DEFAULT_SLEEP_TIME_MS;
    ResetInactiveTimer();

    std::unique_ptr<IDeviceStateAction> mock(mockAction);
    if (stateAction_ != nullptr) {
        stateAction_.reset();
    }
    stateAction_ = std::move(mock);
}

void PowerStateMachine::NotifyPowerStateChanged(PowerState state, StateChangeReason reason)
{
    if (GetState() == PowerState::INACTIVE &&
        !enabledScreenOffEvent_.load(std::memory_order_relaxed) &&
        reason == StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK) {
        POWER_HILOGI(FEATURE_POWER_STATE, "[UL_POWER] not notify inactive power state");
        return;
    }
    POWER_HILOGD(
        FEATURE_POWER_STATE, "state=%{public}u, listeners.size=%{public}zu", state, syncPowerStateListeners_.size());
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "STATE", HiviewDFX::HiSysEvent::EventType::STATISTIC, "STATE",
        static_cast<uint32_t>(state));
#endif
    std::lock_guard lock(mutex_);
    int64_t now = GetTickCount();
    // Send Notification event
    SendEventToPowerMgrNotify(state, now, PowerUtils::GetReasonTypeString(reason));
    uint32_t ffrtId = ffrt::this_task::get_id();
    // Call back all native function
    for (auto& listener : asyncPowerStateListeners_) {
        auto iter = cachedRegister_.find(listener);
        auto pidUid = ((iter != cachedRegister_.end()) ? iter->second : std::make_pair(0, 0));
        // IPowerStateCallback calling pid uid
        POWER_HILOGI(FEATURE_POWER_STATE, "APSCb P=%{public}dU=%{public}dffrtId=%{public}u",
            pidUid.first, pidUid.second, ffrtId);
        listener->OnAsyncPowerStateChanged(state);
        POWER_HILOGI(FEATURE_POWER_STATE, "APSCb End");
    }
#ifdef HAS_HIVIEWDFX_HITRACE_PART
    HitraceScopedEx powerHitrace(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_POWER, "StateListener");
#endif
    for (auto& listener : syncPowerStateListeners_) {
        auto iter = cachedRegister_.find(listener);
        auto pidUid = ((iter != cachedRegister_.end()) ? iter->second : std::make_pair(0, 0));
        // IPowerStateCallback calling pid uid
        POWER_HILOGI(FEATURE_POWER_STATE, "IPSCb P=%{public}dU=%{public}dffrtId=%{public}u",
            pidUid.first, pidUid.second, ffrtId);
        listener->OnPowerStateChanged(state);
        POWER_HILOGI(FEATURE_POWER_STATE, "IPSCb End");
    }
}

void PowerStateMachine::SendEventToPowerMgrNotify(PowerState state, int64_t callTime, const std::string& reason)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Pms is nullptr");
        return;
    }
    auto notify = pms->GetPowerMgrNotify();
    if (notify == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Notify is null");
        return;
    }
    auto screenCommonEventController = DelayedSingleton<ScreenCommonEventController>::GetInstance();
    if (screenCommonEventController == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "PowerStateMachine ScreenCommonEventController is nullptr.");
        return;
    }
    switch (state) {
        case PowerState::AWAKE: {
            screenCommonEventController->SendCustomizedScreenEvent(notify, PowerState::AWAKE, callTime, reason);
            isAwakeNotified_.store(true, std::memory_order_relaxed);
#ifdef POWER_MANAGER_ENABLE_FORCE_SLEEP_BROADCAST
            auto suspendController = pms->GetSuspendController();
            if (suspendController != nullptr && suspendController->GetForceSleepingFlag()) {
                notify->PublishExitForceSleepEvents(callTime);
                POWER_HILOGI(FEATURE_POWER_STATE, "Set flag of force sleeping to false");
                suspendController->SetForceSleepingFlag(false);
            }
#endif
            break;
        }
        case PowerState::INACTIVE: {
            screenCommonEventController->SendCustomizedScreenEvent(notify, PowerState::INACTIVE, callTime, reason);
            isAwakeNotified_.store(false, std::memory_order_relaxed);
            break;
        }
        case PowerState::SLEEP: {
#ifdef POWER_MANAGER_ENABLE_FORCE_SLEEP_BROADCAST
            auto suspendController = pms->GetSuspendController();
            if (suspendController != nullptr && suspendController->GetForceSleepingFlag()) {
                notify->PublishEnterForceSleepEvents(callTime);
            }
            break;
#endif
            POWER_HILOGI(FEATURE_POWER_STATE, "No need to publish EnterForceSleepEvent, state:%{public}u", state);
            break;
        }
        default:
            POWER_HILOGI(FEATURE_POWER_STATE, "No need to publish event, state:%{public}u", state);
    }
}

void PowerStateMachine::PowerStateCallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
{
    if (remote == nullptr || remote.promote() == nullptr) {
        return;
    }
    sptr<IPowerStateCallback> callback = iface_cast<IPowerStateCallback>(remote.promote());
    FFRTTask unRegFunc = [callback] {
        auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
        if (pms == nullptr) {
            POWER_HILOGE(FEATURE_POWER_STATE, "Pms is nullptr");
            return;
        }
        pms->UnRegisterPowerStateCallback(callback);
    };
    FFRTUtils::SubmitTask(unRegFunc);
}

void PowerStateMachine::SetProxFilteringStrategy(ProxFilteringStrategy strategy)
{
#ifdef POWER_MANAGER_SUPPORT_FILTERING_PROXIMITY_EVENT
    isProximityCloseEventFiltered_.store(
        strategy == ProxFilteringStrategy::FILTERING_CLOSE, std::memory_order_relaxed);
    POWER_HILOGI(FEATURE_POWER_STATE, "SetProxFilteringStrategy: %{public}d", static_cast<int32_t>(strategy));
#endif
}

bool PowerStateMachine::FilterProximityCloseEvent()
{
#ifdef POWER_MANAGER_SUPPORT_FILTERING_PROXIMITY_EVENT
    return isProximityCloseEventFiltered_.load(std::memory_order_relaxed);
#endif
    return false;
}

void PowerStateMachine::HandleProximityClose()
{
    if (FilterProximityCloseEvent()) {
        POWER_HILOGI(FEATURE_POWER_STATE, "proximity close intercept, exit proximity-screen-off task");
        return;
    }
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Pms is nullptr");
        return;
    }
    auto suspendController = pms->GetSuspendController();
    if (suspendController == nullptr) {
        POWER_HILOGW(
            FEATURE_POWER_STATE, "suspendController is nullptr, exit proximity-screen-off task");
        return;
    }
    bool ret = SetState(PowerState::INACTIVE, StateChangeReason::STATE_CHANGE_REASON_PROXIMITY, true);
    if (ret) {
        suspendController->StartSleepTimer(SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION,
            static_cast<uint32_t>(SuspendAction::ACTION_AUTO_SUSPEND), 0);
    }
}

void PowerStateMachine::SetDelayTimer(int64_t delayTime, int32_t event)
{
    if (!ffrtTimer_) {
        POWER_HILOGE(FEATURE_ACTIVITY, "Failed to set delay timer, the timer pointer is null");
        return;
    }
    POWER_HILOGD(FEATURE_ACTIVITY, "Set delay timer, delayTime=%{public}s, event=%{public}d",
        std::to_string(delayTime).c_str(), event);

    switch (event) {
        case CHECK_USER_ACTIVITY_TIMEOUT_MSG: {
            FFRTTask task = [this] { this->HandleActivityTimeout(); };
            ffrtTimer_->SetTimer(TIMER_ID_USER_ACTIVITY_TIMEOUT, task, delayTime);
            break;
        }
        case CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG: {
            auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
            auto suspendController = pms->GetSuspendController();
            if (suspendController == nullptr) {
                POWER_HILOGW(FEATURE_ACTIVITY, "suspendController is nullptr");
                return;
            }
            suspendController->HandleEvent(delayTime);
            break;
        }
        case CHECK_PROXIMITY_SCREEN_OFF_MSG: {
            FFRTTask delayScreenOffTask = [this] {
                POWER_HILOGI(FEATURE_POWER_STATE, "proximity-screen-off timer task is triggered");
                proximityScreenOffTimerStarted_.store(false, std::memory_order_relaxed);
                HandleProximityClose();
            };
            ffrtTimer_->SetTimer(TIMER_ID_PROXIMITY_SCREEN_OFF, delayScreenOffTask, delayTime);
            proximityScreenOffTimerStarted_.store(true, std::memory_order_relaxed);
            break;
        }
        default: {
            break;
        }
    }
}

void PowerStateMachine::SetDelayTimer(int64_t delayTime, int32_t event, FFRTTask& task)
{
    if (!ffrtTimer_) {
        POWER_HILOGE(FEATURE_ACTIVITY, "Failed to set delay timer, the timer pointer is null");
        return;
    }
    ffrtTimer_->SetTimer(event, task, delayTime);
}

void PowerStateMachine::CancelDelayTimer(int32_t event)
{
    if (!ffrtTimer_) {
        POWER_HILOGE(FEATURE_ACTIVITY, "Failed to cancel delay timer, the timer pointer is null");
        return;
    }
    POWER_HILOGD(FEATURE_ACTIVITY, "Cancel delay timer, event: %{public}d", event);

    switch (event) {
        case CHECK_USER_ACTIVITY_TIMEOUT_MSG: {
            ffrtTimer_->CancelTimer(TIMER_ID_USER_ACTIVITY_TIMEOUT);
            break;
        }
        case CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG: {
            auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
            auto suspendController = pms->GetSuspendController();
            if (suspendController == nullptr) {
                POWER_HILOGW(FEATURE_ACTIVITY, "suspendController is nullptr");
                return;
            }
            suspendController->CancelEvent();
            break;
        }
        case CHECK_PRE_BRIGHT_AUTH_TIMEOUT_MSG: {
            ffrtTimer_->CancelTimer(TIMER_ID_PRE_BRIGHT_AUTH);
            break;
        }
        case CHECK_PROXIMITY_SCREEN_OFF_MSG: {
            ffrtTimer_->CancelTimer(TIMER_ID_PROXIMITY_SCREEN_OFF);
            proximityScreenOffTimerStarted_.store(false, std::memory_order_relaxed);
            break;
        }
        case CHECK_PROXIMITY_SCREEN_SWITCH_TO_SUB_MSG: {
            ffrtTimer_->CancelTimer(TIMER_ID_PROXIMITY_SCREEN_SWITCH_TO_SUB);
            break;
        }
        default: {
            break;
        }
    }
}

void PowerStateMachine::ResetInactiveTimer(bool needPrintLog)
{
    // change the flag to notify the thread which is setting DIM
    int64_t expectedFlag = static_cast<int64_t>(PowerState::DIM);
    settingStateFlag_.compare_exchange_strong(
        expectedFlag, static_cast<int64_t>(SettingStateFlag::StateFlag::SETTING_DIM_INTERRUPTED));
    CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_TIMEOUT_MSG);
    CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG);
    PublishRefreshEvent();
    if (this->GetDisplayOffTime() < 0) {
        if (needPrintLog) {
            POWER_HILOGI(FEATURE_ACTIVITY, "Auto display off is disabled");
        }
        return;
    }

    int64_t displayOffTime = this->GetDisplayOffTime();
    ResetScreenOffPreTimeForSwing(displayOffTime);
    this->SetDelayTimer(
        displayOffTime - this->GetDimTime(displayOffTime), PowerStateMachine::CHECK_USER_ACTIVITY_TIMEOUT_MSG);
    if (needPrintLog) {
        POWER_HILOGI(FEATURE_ACTIVITY, "reset inactive timer: %{public}" PRId64, displayOffTime);
    }
}

void PowerStateMachine::PublishRefreshEvent()
{
#ifdef POWER_MANAGER_SCREEN_SAVER
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Pms is null");
        return;
    }
    auto notify  = pms->GetPowerMgrNotify();
    if (notify == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Notify is null");
        return;
    }
    POWER_HILOGD(FEATURE_SUSPEND, "Start to publish power refresh event.");
    AAFwk::Want want;
    want.SetAction("usual.event.power.USER_ACTIVITY");
    notify->PublishCustomizedEvent(want);
#endif
}

void PowerStateMachine::ResetScreenOffPreTimeForSwing(int64_t displayOffTime)
{
    int64_t now = GetTickCount();
    int64_t nextTimeOut = now + displayOffTime - this->GetDimTime(displayOffTime);
    POWER_HILOGD(FEATURE_SCREEN_OFF_PRE,
        "now=%{public}lld,displayOffTime=%{public}lld,nextTimeOut=%{public}lld",
        static_cast<long long>(now), static_cast<long long>(displayOffTime), static_cast<long long>(nextTimeOut));
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    auto screenOffPreController = pms->GetScreenOffPreController();
    if (screenOffPreController != nullptr && screenOffPreController->IsRegistered()) {
        screenOffPreController->SchedulEyeDetectTimeout(nextTimeOut, now);
    }
}

void PowerStateMachine::ResetSleepTimer()
{
    CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_TIMEOUT_MSG);
    CancelDelayTimer(PowerStateMachine::CHECK_USER_ACTIVITY_OFF_TIMEOUT_MSG);
    if (this->GetSleepTime() < 0) {
        POWER_HILOGD(FEATURE_ACTIVITY, "Auto sleep is disabled");
        return;
    }
}

void PowerStateMachine::SetAutoSuspend(SuspendDeviceType type, uint32_t delay)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Pms is nullptr");
        return;
    }
    auto suspendController = pms->GetSuspendController();
    if (suspendController == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "Suspend controller is nullptr");
        return;
    }
    suspendController->StartSleepTimer(type, static_cast<uint32_t>(SuspendAction::ACTION_AUTO_SUSPEND), delay);
    POWER_HILOGD(FEATURE_SUSPEND, "Set auto suspend finish");
}

void PowerStateMachine::ShowCurrentScreenLocks()
{
    auto pms = pms_.promote();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_RUNNING_LOCK, "Pms is nullptr");
        return;
    }
    std::map<std::string, RunningLockInfo> screenOnLockLists;
    pms_->QueryRunningLockListsInner(screenOnLockLists);
    std::string message;
    uint32_t mapSize = screenOnLockLists.size();
    uint32_t counter = 0;
    for (auto it : screenOnLockLists) {
        counter++;
        message.append(std::to_string(counter)).append(". ")
            .append("bundleName=").append(it.second.bundleName)
            .append(" name=").append(it.second.name)
            .append(" pid=").append(std::to_string(it.second.pid))
            .append(". ");
    }
    if (counter == 0) {
        return;
    }
    POWER_HILOGI(FEATURE_RUNNING_LOCK, "%{public}d screen on locks as follows: %{public}s", mapSize, message.c_str());
}

#ifdef HAS_SENSORS_SENSOR_PART
bool PowerStateMachine::IsProximityClose()
{
    auto pms = pms_.promote();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_RUNNING_LOCK, "Pms is nullptr");
        return false;
    }
    auto runningLockMgr = pms->GetRunningLockMgr();
    if (runningLockMgr == nullptr) {
        POWER_HILOGE(FEATURE_RUNNING_LOCK, "RunningLockMgr is nullptr");
        return false;
    }
    return runningLockMgr->IsProximityClose();
}
#endif

void PowerStateMachine::HandleActivityTimeout()
{
    POWER_HILOGD(FEATURE_ACTIVITY, "Enter, displayState = %{public}d", stateAction_->GetDisplayState());
    SetState(PowerState::DIM, StateChangeReason::STATE_CHANGE_REASON_TIMEOUT);
}

void PowerStateMachine::HandleActivitySleepTimeout()
{
    POWER_HILOGD(FEATURE_ACTIVITY, "Enter, displayState = %{public}d", stateAction_->GetDisplayState());
    if (!this->CheckRunningLock(PowerState::SLEEP)) {
        POWER_HILOGW(FEATURE_POWER_STATE, "RunningLock is blocking to transit to SLEEP");
        return;
    }
    DisplayState dispState = stateAction_->GetDisplayState();
    if (dispState == DisplayState::DISPLAY_OFF) {
        SetState(PowerState::SLEEP, StateChangeReason::STATE_CHANGE_REASON_TIMEOUT);
    } else {
        POWER_HILOGW(FEATURE_ACTIVITY, "Display is on, ignore activity sleep timeout, state = %{public}d", dispState);
    }
}

void PowerStateMachine::HandleSystemWakeup()
{
    POWER_HILOGD(FEATURE_WAKEUP, "Enter, displayState = %{public}d", stateAction_->GetDisplayState());
    if (IsScreenOn()) {
        SetState(PowerState::AWAKE, StateChangeReason::STATE_CHANGE_REASON_SYSTEM, true);
    } else {
        SetState(PowerState::INACTIVE, StateChangeReason::STATE_CHANGE_REASON_SYSTEM, true);
    }
}

void PowerStateMachine::SetForceTimingOut(bool enabled)
{
    bool isScreenOnLockActive = IsRunningLockEnabled(RunningLockType::RUNNINGLOCK_SCREEN);
    bool currentValue = forceTimingOut_.exchange(enabled);
    pid_t pid = IPCSkeleton::GetCallingPid();
    auto uid = IPCSkeleton::GetCallingUid();
    PowerState curState = GetState();
    if (!enabled) {
        g_callSetForceTimingOutPid = 0;
        g_callSetForceTimingOutUid = 0;
    } else {
        g_callSetForceTimingOutPid = pid;
        g_callSetForceTimingOutUid = uid;
    }
    POWER_HILOGI(FEATURE_RUNNING_LOCK,
        "SetForceTimingOut: %{public}s -> %{public}s, screenOnLockActive=%{public}s, PowerState=%{public}u, "
        "PID=%{public}d, UID=%{public}d",
        currentValue ? "TRUE" : "FALSE", enabled ? "TRUE" : "FALSE", isScreenOnLockActive ? "TRUE" : "FALSE", curState,
        pid, uid);
    if (currentValue == enabled || !isScreenOnLockActive || IsSettingState(PowerState::DIM)) {
        // no need to interact with screen state or timer
        return;
    }
    if (enabled) {
        // In case the PowerState is AWAKE, we need to reset the timer since there is no existing one.
        // Only reset the timer if no SetState operation is currently in progress, and if any,
        // make sure this ResetInactiveTimer operation does not interfere with it.
        // Because the goal here is to ensure that there exist some Timer, regardless who sets the timer.
        // I call it "weak" ResetInactiveTimer to distinguish it from the "strong" one invoked by RefreshActivity,
        // which (should) invalidates any time-out timer previously set.
        if (stateMutex_.try_lock()) {
            if (GetState() == PowerState::AWAKE) {
                ResetInactiveTimer();
            }
            stateMutex_.unlock();
        }
    } else {
        // SetForceTimingOut from TRUE to FALSE, with screen-on-lock active.
        // Need to exit DIM and/or reset(cancel) timer
        SetState(PowerState::AWAKE, StateChangeReason::STATE_CHANGE_REASON_REFRESH);
    }
}

void PowerStateMachine::LockScreenAfterTimingOut(bool enabled, bool checkScreenOnLock, bool sendScreenOffEvent)
{
    pid_t pid = IPCSkeleton::GetCallingPid();
    auto uid = IPCSkeleton::GetCallingUid();
    POWER_HILOGI(FEATURE_RUNNING_LOCK,
        "LockScreenAfterTimingOut: %{public}u, %{public}u, %{public}u, PID=%{public}d, UID=%{public}d",
        static_cast<uint32_t>(enabled), static_cast<uint32_t>(checkScreenOnLock),
        static_cast<uint32_t>(sendScreenOffEvent), pid, uid);
    enabledTimingOutLockScreen_.store(enabled, std::memory_order_relaxed);
    enabledTimingOutLockScreenCheckLock_.store(checkScreenOnLock, std::memory_order_relaxed);
    enabledScreenOffEvent_.store(sendScreenOffEvent, std::memory_order_relaxed);
}

void PowerStateMachine::SetEnableDoze(bool enable)
{
    isDozeEnabled_.store(enable, std::memory_order_relaxed);
}

bool PowerStateMachine::SetDozeMode(DisplayState state)
{
    std::lock_guard<ffrt::mutex> lock(stateMutex_);
    if (IsScreenOn()) {
        POWER_HILOGW(FEATURE_POWER_STATE, "the screen is on, not allowed to set doze mode");
        return false;
    }
    uint32_t ret =
        this->stateAction_->SetDisplayState(state, StateChangeReason::STATE_CHANGE_REASON_SWITCHING_DOZE_MODE);
    return ret == ActionResult::SUCCESS;
}

#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
void PowerStateMachine::SetInternalScreenDisplayState(DisplayState state, StateChangeReason reason)
{
    std::lock_guard<ffrt::mutex> lock(internalScreenStateMutex_);
    uint32_t ffrtId = ffrt::this_task::get_id();
    if (state == DisplayState::DISPLAY_ON) {
#ifdef POWER_MANAGER_POWER_ENABLE_S4
        if (IsHibernating()) {
            POWER_HILOGI(FEATURE_POWER_STATE,
                "[UL_POWER] Do not power the internal screen while hibernating, ffrtId=%{public}u", ffrtId);
            return;
        }
#endif
        if (!IsSwitchOpen()) {
            POWER_HILOGI(FEATURE_POWER_STATE,
                "[UL_POWER] Do not power the internal screen while switch is close, ffrtId=%{public}u", ffrtId);
            return;
        }
        this->stateAction_->SetInternalScreenDisplayPower(state, reason);
        this->stateAction_->SetInternalScreenBrightness();
    } else if (state == DisplayState::DISPLAY_OFF) {
        this->stateAction_->SetInternalScreenDisplayPower(state, reason);
    } else {
        POWER_HILOGW(FEATURE_POWER_STATE,
            "[UL_POWER] SetInternalScreenDisplayState, invalid display state: %{public}u, ffrtId=%{public}u",
            state, ffrtId);
    }
}
#endif

bool PowerStateMachine::CheckRunningLock(PowerState state)
{
    POWER_HILOGD(FEATURE_RUNNING_LOCK, "Enter, state = %{public}u", state);
    auto pms = pms_.promote();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_RUNNING_LOCK, "Pms is nullptr");
        return false;
    }
    auto runningLockMgr = pms->GetRunningLockMgr();
    if (runningLockMgr == nullptr) {
        POWER_HILOGE(FEATURE_RUNNING_LOCK, "RunningLockMgr is nullptr");
        return false;
    }
    if (state == PowerState::DIM) {
        // screen on lock need to block DIM state as well
        state = PowerState::INACTIVE;
        POWER_HILOGD(FEATURE_RUNNING_LOCK, "check Screen on Lock for DIM state");
    }
    auto iterator = lockMap_.find(state);
    if (iterator == lockMap_.end()) {
        POWER_HILOGI(FEATURE_RUNNING_LOCK, "No specific lock in lockMap_ for state: %{public}u", state);
        return true;
    }

    std::shared_ptr<std::vector<RunningLockType>> pLock = iterator->second;
    for (std::vector<RunningLockType>::const_iterator iter = pLock->begin(); iter != pLock->end(); ++iter) {
        uint32_t count = runningLockMgr->GetValidRunningLockNum(*iter);
        if (count > 0) {
            POWER_HILOGD(FEATURE_POWER_STATE,
                "RunningLock %{public}s is locking (count=%{public}d), blocking %{public}s",
                PowerUtils::GetRunningLockTypeString(*iter).c_str(), count,
                PowerUtils::GetPowerStateString(state).c_str());
            return false;
        }
    }

    POWER_HILOGD(FEATURE_RUNNING_LOCK, "No specific lock for state: %{public}u", state);
    return true;
}

bool PowerStateMachine::IsRunningLockEnabled(RunningLockType type)
{
    auto pms = pms_.promote();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Pms is nullptr");
        return false;
    }
    auto runningLockMgr = pms->GetRunningLockMgr();
    if (runningLockMgr == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "RunningLockMgr is nullptr");
        return false;
    }
    if (runningLockMgr->GetValidRunningLockNum(type) > 0) {
        return true;
    }
    return false;
}

void PowerStateMachine::SetDisplayOffTime(int64_t time, bool needUpdateSetting)
{
    pid_t pid = IPCSkeleton::GetCallingPid();
    auto uid = IPCSkeleton::GetCallingUid();
    // set display off time, calling pid uid, n=needUpdateSetting, i=isScreenOffTimeOverride_
    POWER_HILOGI(FEATURE_POWER_STATE,
        "setoff T%{public}" PRId64 "->%{public}" PRId64 "P:%{public}dU:%{public}dn=%{public}di=%{public}d",
        displayOffTime_.load(), time, pid, uid, needUpdateSetting, isScreenOffTimeOverride_);
    displayOffTime_ = time;
    if (currentState_ == PowerState::AWAKE) {
        if (isScreenOffTimeOverride_ == true) {
            ResetInactiveTimer(false);
        } else {
            ResetInactiveTimer();
        }
    }
    if (needUpdateSetting) {
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
        SettingHelper::SetSettingDisplayAcScreenOffTime(displayOffTime_);
        SettingHelper::SetSettingDisplayDcScreenOffTime(displayOffTime_);
#else
        SettingHelper::SetSettingDisplayOffTime(displayOffTime_);
#endif
    }
}

void PowerStateMachine::DisplayOffTimeUpdateFunc()
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "get PowerMgrService fail");
        return;
    }
    auto stateMachine = pms->GetPowerStateMachine();
    if (stateMachine == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "get PowerStateMachine fail");
        return;
    }

    int64_t systemTime = stateMachine->GetDisplayOffTime();
    int64_t settingTime = pms->GetSettingDisplayOffTime(systemTime);
    if (settingTime == systemTime) {
        POWER_HILOGI(FEATURE_POWER_STATE, "setting display off time %{public}" PRId64 " already worked", settingTime);
        return;
    }
    POWER_HILOGI(FEATURE_POWER_STATE, "setting update display off time %{public}" PRId64 " -> %{public}" PRId64 "",
        systemTime, settingTime);
    g_beforeOverrideTime = settingTime;
    auto policy = DelayedSingleton<PowerModePolicy>::GetInstance();
    if (policy == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "get PowerModePolicy fail");
        return;
    }
    policy->RemoveBackupMapSettingSwitch(PowerModePolicy::ServiceType::DISPLAY_OFFTIME);
    stateMachine->SetDisplayOffTime(settingTime, false);
}

void PowerStateMachine::RegisterDisplayOffTimeObserver()
{
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_displayOffTimeAcObserver && g_displayOffTimeDcObserver) {
#else
    if (g_displayOffTimeObserver) {
#endif
        POWER_HILOGI(FEATURE_POWER_STATE, "setting display off time observer is already registered");
        return;
    }
    DisplayOffTimeUpdateFunc();
    SettingObserver::UpdateFunc updateFunc = [&](const std::string&) {
        PowerStateMachine::DisplayOffTimeUpdateFunc();
    };
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_displayOffTimeAcObserver == nullptr) {
        g_displayOffTimeAcObserver = SettingHelper::RegisterSettingDisplayAcScreenOffTimeObserver(updateFunc);
    }
    if (g_displayOffTimeDcObserver == nullptr) {
        g_displayOffTimeDcObserver = SettingHelper::RegisterSettingDisplayDcScreenOffTimeObserver(updateFunc);
    }
#else
    g_displayOffTimeObserver = SettingHelper::RegisterSettingDisplayOffTimeObserver(updateFunc);
#endif
}

void PowerStateMachine::UnregisterDisplayOffTimeObserver()
{
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (g_displayOffTimeAcObserver) {
        SettingHelper::UnregisterSettingObserver(g_displayOffTimeAcObserver);
        g_displayOffTimeAcObserver = nullptr;
    }
    if (g_displayOffTimeDcObserver) {
        SettingHelper::UnregisterSettingObserver(g_displayOffTimeDcObserver);
        g_displayOffTimeDcObserver = nullptr;
    }
#else
    if (g_displayOffTimeObserver == nullptr) {
        POWER_HILOGD(FEATURE_POWER_STATE, "g_displayOffTimeObserver is nullptr, no need to unregister");
        return;
    }
    SettingHelper::UnregisterSettingObserver(g_displayOffTimeObserver);
    g_displayOffTimeObserver = nullptr;
#endif
}

void PowerStateMachine::SetSleepTime(int64_t time)
{
    sleepTime_ = time;
}

int64_t PowerStateMachine::GetDisplayOffTime()
{
    return displayOffTime_;
}

int64_t PowerStateMachine::GetDimTime(int64_t displayOffTime)
{
    int64_t dimTime = displayOffTime / OFF_TIMEOUT_FACTOR;
#ifdef POWER_MANAGER_ENABLE_LONG_TIME_DIM
    constexpr int64_t DEFAULT_ACTIVE_TIME_MS = 600000; //10min
    int64_t maxActiveTime = activeTimeBeforeLongTimeDim_;
    if (displayOffTime > 0 && maxActiveTime >= DEFAULT_ACTIVE_TIME_MS && displayOffTime > maxActiveTime) {
        dimTime = displayOffTime - maxActiveTime;
        POWER_HILOGD(FEATURE_POWER_STATE,
            "long time dim enable, dimTime: %{public}ld, displayOffTime: %{public}ld, maxActiveTime: %{public}ld",
            dimTime, displayOffTime, maxActiveTime);
        return std::clamp(dimTime, static_cast<int64_t>(0), displayOffTime);
    }
#endif
    return std::clamp(dimTime, static_cast<int64_t>(0), MAX_DIM_TIME_MS);
}

bool PowerStateMachine::IsSettingState(PowerState state)
{
    int64_t flag = settingStateFlag_.load();
    bool matched = flag == static_cast<int64_t>(state);
    if (matched) {
        return true;
    } else {
        return (
            state == PowerState::DIM && flag == static_cast<int64_t>(SettingStateFlag::StateFlag::FORCE_SETTING_DIM));
    }
}

int64_t PowerStateMachine::GetSleepTime()
{
    return sleepTime_;
}

PowerStateMachine::ScreenChangeCheck::ScreenChangeCheck(PowerState state, StateChangeReason reason)
    : state_(state),
      reason_(reason)
{
    // only check for screen on/off event
    if (state != PowerState::INACTIVE && state != PowerState::AWAKE) {
        return;
    }

    pid_ = getpid();
    uid_ = static_cast<pid_t>(getuid());
    int64_t submitTime = GetTickCount();

    FFRTTask task = [checker = (*this), submitTime]() {
        checker.ReportSysEvent("TIMEOUT: timer started at " + std::to_string(submitTime));
        checker.SetReportTimerStartFlag(false);
    };

    handle_ = ffrt::submit_h(task, ffrt::task_attr().qos(ffrt::qos_user_interactive).delay(SCREEN_CHANGE_TIMEOUT_US));
    isReportTimerStarted_ = true;
}

PowerStateMachine::ScreenChangeCheck::~ScreenChangeCheck() noexcept
{
    if (!isReportTimerStarted_) {
        return;
    }
    // the callee does the nullptr check
    ffrt::skip(handle_);
}

void PowerStateMachine::ScreenChangeCheck::SetReportTimerStartFlag(bool flag) const
{
    isReportTimerStarted_ = flag;
}

void PowerStateMachine::ScreenChangeCheck::ReportSysEvent(const std::string& msg) const
{
    const char* eventName = (state_ == PowerState::INACTIVE) ? "SCREEN_OFF_TIMEOUT" : "SCREEN_ON_TIMEOUT";
    POWER_HILOGE(FEATURE_POWER_STATE,
        "event=%{public}s, reason=%{public}s, msg=%{public}s, pid=%{public}d,"
        " uid=%{public}d",
        eventName, PowerUtils::GetReasonTypeString(reason_).c_str(), msg.c_str(), pid_, uid_);

    static int64_t lastReportTime = -1;
    int64_t now = GetTickCount();
    int64_t nextReportTime = lastReportTime + SCREEN_CHANGE_REPORT_INTERVAL_MS;
    if (nextReportTime > SCREEN_CHANGE_REPORT_INTERVAL_MS && now < nextReportTime) {
        POWER_HILOGD(FEATURE_POWER_STATE, "Will skip report for another %{public}s ms",
            std::to_string(nextReportTime - now).c_str());
        return;
    }
    lastReportTime = now;
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, eventName, HiviewDFX::HiSysEvent::EventType::FAULT, "PID",
        pid_, "UID", uid_, "PACKAGE_NAME", "", "PROCESS_NAME", "", "MSG", msg.c_str(), "REASON",
        PowerUtils::GetReasonTypeString(reason_).c_str());
#endif
}

std::shared_ptr<PowerStateMachine::StateController> PowerStateMachine::GetStateController(PowerState state)
{
    auto iterator = controllerMap_.find(state);
    if (iterator == controllerMap_.end()) {
        return nullptr;
    }
    return iterator->second;
}

bool PowerStateMachine::NeedShowScreenLocks(PowerState state)
{
    return state == PowerState::AWAKE ||
        state == PowerState::INACTIVE || state == PowerState::DIM;
}

void PowerStateMachine::UpdateSettingStateFlag(PowerState state, StateChangeReason reason)
{
    if ((reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT ||
        reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) &&
        GetState() != PowerState::AWAKE) {
        settingOnStateFlag_ = false;
        settingOffStateFlag_ = true;
        return;
    }
    settingOnStateFlag_ = (state == PowerState::AWAKE);
    settingOffStateFlag_ = (state == PowerState::INACTIVE);
}

void PowerStateMachine::RestoreSettingStateFlag()
{
    settingOnStateFlag_ = false;
    settingOffStateFlag_ = false;
}

void PowerStateMachine::HandleProximityScreenOffTimer(PowerState state, StateChangeReason reason)
{
#ifdef HAS_SENSORS_SENSOR_PART
    if (!proximityScreenOffTimerStarted_.load()) {
        return;
    }
    if ((reason == StateChangeReason::STATE_CHANGE_REASON_DOUBLE_CLICK ||
            reason == StateChangeReason::STATE_CHANGE_REASON_PICKUP) &&
        IsProximityClose() && state == PowerState::AWAKE) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Double-click or pickup is not allowed to cancel proximity-screen-off timer");
        return;
    }
    if (reason != StateChangeReason::STATE_CHANGE_REASON_PROXIMITY) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Cancel proximity-screen-off timer, reason:%{public}s",
            PowerUtils::GetReasonTypeString(reason).c_str());
        CancelDelayTimer(PowerStateMachine::CHECK_PROXIMITY_SCREEN_OFF_MSG);
        return;
    }
    if (state == PowerState::AWAKE) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Cancel proximity-screen-off timer, reason:%{public}s(away)",
            PowerUtils::GetReasonTypeString(reason).c_str());
        CancelDelayTimer(PowerStateMachine::CHECK_PROXIMITY_SCREEN_OFF_MSG);
    }
#endif
}

bool PowerStateMachine::HandlePreBrightState(PowerState targetState, StateChangeReason reason)
{
    bool ret = false;
    PowerStateMachine::PreBrightState curState = preBrightState_.load();
    uint32_t ffrtId = ffrt::this_task::get_id();
    POWER_HILOGI(FEATURE_WAKEUP, "[UL_POWER]HandlePreBrightState start ffrtId: %{public}u", ffrtId);
    if (reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT) {
        if (ffrtTimer_ != nullptr) {
            FFRTTask authFailTask = [this] {
                POWER_HILOGI(FEATURE_WAKEUP, "Auth result of PRE_BRIGHT isn't received within %{public}u ms",
                    PRE_BRIGHT_AUTH_TIMER_DELAY_MS);
                const std::string detail = "pre_bright_auth_fail_screen_off";
                const std::string pkgName = "pre_bright_auth_time";
                HandlePreBrightWakeUp(GetTickCount(), WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF,
                    detail, pkgName, true);
            };
            if (curState == PowerStateMachine::PRE_BRIGHT_STARTED) {
                POWER_HILOGI(FEATURE_WAKEUP, "Cancel pre-bright-auth timer, rason=%{public}s",
                    PowerUtils::GetReasonTypeString(reason).c_str());
                CancelDelayTimer(PowerStateMachine::CHECK_PRE_BRIGHT_AUTH_TIMEOUT_MSG);
            }
            POWER_HILOGI(FEATURE_POWER_STATE, "Start pre-bright-auth timer");
            ffrtTimer_->SetTimer(TIMER_ID_PRE_BRIGHT_AUTH, authFailTask, PRE_BRIGHT_AUTH_TIMER_DELAY_MS);
            preBrightState_.store(PowerStateMachine::PRE_BRIGHT_STARTED, std::memory_order_relaxed);
            ret = true;
        }
    } else if (IsPreBrightAuthReason(reason)) {
        if (curState == PowerStateMachine::PRE_BRIGHT_STARTED) {
            preBrightState_.store(PowerStateMachine::PRE_BRIGHT_FINISHED, std::memory_order_relaxed);
            ret = true;
        } else {
            POWER_HILOGW(
                FEATURE_POWER_STATE, "prebright first stage is not triggered, skip handling prebright auth result");
        }
    } else {
        if (targetState != PowerState::SLEEP && curState == PowerStateMachine::PRE_BRIGHT_STARTED) {
            POWER_HILOGI(FEATURE_WAKEUP, "Cancel pre-bright-auth timer, rason=%{public}s",
                PowerUtils::GetReasonTypeString(reason).c_str());
            CancelDelayTimer(PowerStateMachine::CHECK_PRE_BRIGHT_AUTH_TIMEOUT_MSG);
        }
        if (targetState != PowerState::SLEEP) {
            preBrightState_.store(PowerStateMachine::PRE_BRIGHT_UNSTART, std::memory_order_relaxed);
        }
        ret = true;
    }
    POWER_HILOGD(FEATURE_WAKEUP, "Pre bright state: %{public}u", static_cast<uint32_t>(preBrightState_.load()));
    return ret;
}

bool PowerStateMachine::CheckFFRTTaskAvailability(PowerState state, StateChangeReason reason) const
{
    if (!IsTimeoutReason(reason)) {
        return true;
    }
    void* curTask = ffrt_get_cur_task();
    if (curTask == nullptr) {
        // not actually an ffrt task;
        return true;
    }
    if (!ffrtTimer_) {
        POWER_HILOGE(FEATURE_POWER_STATE, "ffrtTimer_ is nullptr");
        return false;
    }
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (curTask == ffrtTimer_->GetTaskHandlePtr(TIMER_ID_AUTO_SLEEP)) {
        return true;
    }
#endif
    const void* pendingTask = nullptr;
    switch (state) {
        case PowerState::DIM:
            pendingTask = ffrtTimer_->GetTaskHandlePtr(TIMER_ID_USER_ACTIVITY_TIMEOUT);
            break;
        case PowerState::INACTIVE:
            pendingTask = ffrtTimer_->GetTaskHandlePtr(TIMER_ID_USER_ACTIVITY_OFF);
            break;
        default:
            pendingTask = ffrtTimer_->GetTaskHandlePtr(TIMER_ID_SLEEP);
            break;
    }
    return curTask == pendingTask;
}

bool PowerStateMachine::IsTimeoutReason(StateChangeReason reason) const
{
    return reason == StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK ||
        reason == StateChangeReason::STATE_CHANGE_REASON_TIMEOUT;
}

bool PowerStateMachine::SetState(PowerState state, StateChangeReason reason, bool force)
{
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    int32_t beginTimeMs = GetTickCount();
#endif
    uint32_t ffrtId = ffrt::this_task::get_id();
    POWER_HILOGD(FEATURE_POWER_STATE, "state=%{public}s, reason=%{public}s, force=%{public}d, ffrtId=%{public}u",
        PowerUtils::GetPowerStateString(state).c_str(),
        PowerUtils::GetReasonTypeString(reason).c_str(), force, ffrtId);
    std::lock_guard<ffrt::mutex> lock(stateMutex_);
    if (!CheckFFRTTaskAvailability(state, reason)) {
        POWER_HILOGI(FEATURE_POWER_STATE, "this timeout task is invalidated, directly return");
        return false;
    }
    ScreenChangeCheck timeoutCheck(state, reason);
    SettingStateFlag flag(state, shared_from_this(), reason);

    if (NeedShowScreenLocks(state)) {
        ShowCurrentScreenLocks();
    }

    HandleProximityScreenOffTimer(state, reason);
    std::shared_ptr<StateController> pController = GetStateController(state);
    if (pController == nullptr) {
        POWER_HILOGW(FEATURE_POWER_STATE, "StateController is not init");
        return false;
    }
    if (IsTimeoutReason(reason) && forceTimingOut_.load()) {
        force = true;
        POWER_HILOGI(FEATURE_POWER_STATE, "Call SetForceTimingOut PID=%{public}d, UID=%{public}d, ffrtId=%{public}u",
            g_callSetForceTimingOutPid, g_callSetForceTimingOutUid, ffrtId);
    }
    UpdateSettingStateFlag(state, reason);
#ifdef POWER_MANAGER_ENABLE_WATCH_CUSTOMIZED_SCREEN_COMMON_EVENT_RULES
    if (!SetScreenCommonEventRules(reason)) {
        POWER_HILOGE(FEATURE_POWER_STATE, "PowerStateMachine screenCommonEventController is nullptr.");
        return false;
    }
#endif
    auto pms = pms_.promote();
    std::shared_ptr<WakeupController> wakeupController = pms ? pms->GetWakeupController() : nullptr;
    if (wakeupController && state == PowerState::INACTIVE) {
        wakeupController->RegisterMonitor(state);
    }
    TransitResult ret = pController->TransitTo(reason, force);
    if (wakeupController) {
        wakeupController->RegisterMonitor(GetState());
    }
    const auto& [powerkeyPressCacheId, powerkeyReleaseCacheId] = GetPowerKeySubscriberCacheIds();
    POWER_HILOGW(FEATURE_POWER_STATE,"[UL_POWER] StateController::TransitTo %{public}s ret: %{public}d, ffrtId="
        "%{public}u, reason=%{public}s, kp=%{public}d, kr=%{public}d", PowerUtils::GetPowerStateString(state).c_str(),
        ret, ffrtId, PowerUtils::GetReasonTypeString(reason).c_str(), powerkeyPressCacheId, powerkeyReleaseCacheId);
    RestoreSettingStateFlag();
    WriteHiSysEvent(ret, reason, beginTimeMs, state);
    return (ret == TransitResult::SUCCESS || ret == TransitResult::ALREADY_IN_STATE);
}

void PowerStateMachine::WriteHiSysEvent(TransitResult ret, StateChangeReason reason,
    int32_t beginTimeMs, PowerState state)
{
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    constexpr int32_t SETSTATE_ON_TIMEOUT_MS = 400;
    constexpr int32_t SETSTATE_OFF_TIMEOUT_MS = 1000;
    constexpr int32_t pid = 0;
    constexpr int32_t uid = 0;
    if (IsTransitFailed(ret)) {
        POWER_HILOGI(FEATURE_POWER_STATE, "screen state transit result=%{public}d", ret);
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SCREEN_STATE_TRANSIT_FAILED",
            HiviewDFX::HiSysEvent::EventType::FAULT, "TRANSIT_RESULT", static_cast<int32_t>(ret),
            "REASON", PowerUtils::GetReasonTypeString(reason).c_str());
    }
    int32_t endTimeMs = GetTickCount();
    if (endTimeMs - beginTimeMs > SETSTATE_ON_TIMEOUT_MS && state == PowerState::AWAKE) {
        POWER_HILOGI(FEATURE_POWER_STATE, "set state on timeout=%{public}d", (endTimeMs - beginTimeMs));
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "INTERFACE_CONSUMING_TIMEOUT",
            HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PID", pid, "UID", uid, "TYPE",
            static_cast<int32_t>(InterfaceTimeoutType::INTERFACE_TIMEOUT_TYPE_SETSTATE_ON),
            "REASON", PowerUtils::GetReasonTypeString(reason).c_str(), "TIME", (endTimeMs - beginTimeMs));
    } else if ((endTimeMs - beginTimeMs > SETSTATE_ON_TIMEOUT_MS) &&
        (endTimeMs - beginTimeMs < SETSTATE_OFF_TIMEOUT_MS) && (state == PowerState::INACTIVE)) {
        POWER_HILOGI(FEATURE_POWER_STATE, "set state off timeout=%{public}d", (endTimeMs - beginTimeMs));
        HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "INTERFACE_CONSUMING_TIMEOUT",
            HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PID", pid, "UID", uid, "TYPE",
            static_cast<int32_t>(InterfaceTimeoutType::INTERFACE_TIMEOUT_TYPE_SETSTATE_OFF),
            "REASON", PowerUtils::GetReasonTypeString(reason).c_str(), "TIME", (endTimeMs - beginTimeMs));
    }
#endif
}

bool PowerStateMachine::IsTransitFailed(TransitResult ret)
{
    if (ret == TransitResult::OTHER_ERR) {
        return true;
    } else {
        return false;
    }
}

std::pair<int32_t, int32_t> PowerStateMachine::GetPowerKeySubscriberCacheIds()
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Pms is nullptr");
        return {};
    }
    auto suspendController = pms->GetSuspendController();
    if (suspendController == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Suspend controller is nullptr");
        return {};
    }
    auto wakeupController =  pms->GetWakeupController();
    if (wakeupController == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "Wakeup controller is nullptr");
        return {};
    }
    return {wakeupController->GetPowerkeyShortPressIdCache(), suspendController->GetPowerkeyReleaseIdCache()};
}

void PowerStateMachine::SetDisplaySuspend(bool enable)
{
    POWER_HILOGD(FEATURE_POWER_STATE, "enable: %{public}d", enable);
    std::lock_guard<ffrt::mutex> lock(stateMutex_);
    enableDisplaySuspend_ = enable;
    if (GetState() == PowerState::INACTIVE) {
        POWER_HILOGI(FEATURE_POWER_STATE, "Change display state");
        if (enable) {
            stateAction_->SetDisplayState(
                DisplayState::DISPLAY_SUSPEND, StateChangeReason::STATE_CHANGE_REASON_APPLICATION);
        } else {
            stateAction_->SetDisplayState(
                DisplayState::DISPLAY_OFF, StateChangeReason::STATE_CHANGE_REASON_APPLICATION);
        }
    }
}

bool PowerStateMachine::TryToCancelScreenOff()
{
    return stateAction_->TryToCancelScreenOff();
}

void PowerStateMachine::BeginPowerkeyScreenOff()
{
    stateAction_->BeginPowerkeyScreenOff();
}

void PowerStateMachine::EndPowerkeyScreenOff()
{
    stateAction_->EndPowerkeyScreenOff();
}

StateChangeReason PowerStateMachine::GetReasonByWakeType(WakeupDeviceType type)
{
    POWER_HILOGD(FEATURE_WAKEUP, "WakeupDeviceType :%{public}u", type);
    StateChangeReason ret = StateChangeReason::STATE_CHANGE_REASON_UNKNOWN;
    switch (type) {
        case WakeupDeviceType::WAKEUP_DEVICE_POWER_BUTTON:
            ret = StateChangeReason::STATE_CHANGE_REASON_POWER_KEY;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_WAKE_KEY:
            ret = StateChangeReason::STATE_CHANGE_REASON_HARD_KEY;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_APPLICATION:
            ret = StateChangeReason::STATE_CHANGE_REASON_APPLICATION;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PLUGGED_IN: // fall through
        case WakeupDeviceType::WAKEUP_DEVICE_HDMI:
            ret = StateChangeReason::STATE_CHANGE_REASON_CABLE;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_GESTURE:
            ret = StateChangeReason::STATE_CHANGE_REASON_TOUCH;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_CAMERA_LAUNCH:
            ret = StateChangeReason::STATE_CHANGE_REASON_CAMERA;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_WAKE_MOTION:
            ret = StateChangeReason::STATE_CHANGE_REASON_SENSOR;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_LID:
            ret = StateChangeReason::STATE_CHANGE_REASON_LID;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_DOUBLE_CLICK:
            ret = StateChangeReason::STATE_CHANGE_REASON_DOUBLE_CLICK;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PEN:
            ret = StateChangeReason::STATE_CHANGE_REASON_PEN;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_KEYBOARD:
            ret = StateChangeReason::STATE_CHANGE_REASON_KEYBOARD;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_MOUSE:
            ret = StateChangeReason::STATE_CHANGE_REASON_MOUSE;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_SWITCH:
            ret = StateChangeReason::STATE_CHANGE_REASON_SWITCH;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT:
            ret = StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_SUCCESS:
            ret = StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_SUCCESS;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_ON:
            ret = StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_ON;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF:
            ret = StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_AOD_SLIDING:
            ret = StateChangeReason::STATE_CHANGE_REASON_AOD_SLIDING;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_INCOMING_CALL:
            ret = StateChangeReason::STATE_CHANGE_REASON_INCOMING_CALL;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_SHELL:
            ret = StateChangeReason::STATE_CHANGE_REASON_SHELL;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PICKUP:
            ret = StateChangeReason::STATE_CHANGE_REASON_PICKUP;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_EXIT_SYSTEM_STR:
            ret = StateChangeReason::STATE_CHANGE_REASON_EXIT_SYSTEM_STR;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_SCREEN_CONNECT:
            ret = StateChangeReason::STATE_CHANGE_REASON_SCREEN_CONNECT;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_TP_TOUCH:
            ret = StateChangeReason::STATE_CHANGE_REASON_TP_TOUCH;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_EX_SCREEN_INIT:
            ret = StateChangeReason::STATE_CHANGE_REASON_EX_SCREEN_INIT;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_ABNORMAL_SCREEN_CONNECT:
            ret = StateChangeReason::STATE_CHANGE_REASON_ABNORMAL_SCREEN_CONNECT;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_PLUG_CHANGE:
            ret = StateChangeReason::STATE_CHANGE_REASON_PLUG_CHANGE;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_TENT_MODE_CHANGE:
            ret = StateChangeReason::STATE_CHANGE_REASON_TENT_MODE;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_END_DREAM:
            ret = StateChangeReason::STATE_CHANGE_REASON_END_DREAM;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_BLUETOOTH_INCOMING_CALL:
            ret = StateChangeReason::STATE_CHANGE_REASON_BLUETOOTH_INCOMING_CALL;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_FROM_ULSR:
            ret = StateChangeReason::STATE_CHANGE_REASON_WAKEUP_FROM_ULSR;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_MESSAGE_NOTIFICATION:
            ret = StateChangeReason::STATE_CHANGE_REASON_MESSAGE_NOTIFICATION;
            break;
        case WakeupDeviceType::WAKEUP_DEVICE_UNKNOWN: // fall through
        default:
            break;
    }
    POWER_HILOGD(FEATURE_WAKEUP, "StateChangeReason: %{public}u", ret);
    return ret;
}

SuspendDeviceType PowerStateMachine::GetSuspendTypeByReason(StateChangeReason reason)
{
    POWER_HILOGD(FEATURE_SUSPEND, "GetSuspendTypeByReason reason: %{public}u", reason);
    SuspendDeviceType ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION;
    switch (reason) {
        case StateChangeReason::STATE_CHANGE_REASON_TIMEOUT:
            ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK:
            ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_HARD_KEY:
            ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_POWER_KEY;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_SYSTEM:
            ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_FORCE_SUSPEND;
            break;
        case StateChangeReason::STATE_CHANGE_REASON_PEOPLE_LEAVING:
            ret = SuspendDeviceType::SUSPEND_DEVICE_REASON_PEOPLE_LEAVING;
            break;
        default:
            break;
    }
    POWER_HILOGD(FEATURE_SUSPEND, "SuspendDeviceType: %{public}u", ret);
    return ret;
}

StateChangeReason PowerStateMachine::GetReasonBySuspendType(SuspendDeviceType type)
{
    POWER_HILOGD(FEATURE_SUSPEND, "SuspendDeviceType: %{public}u", type);
    StateChangeReason ret = StateChangeReason::STATE_CHANGE_REASON_UNKNOWN;
    switch (type) {
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION:
            ret = StateChangeReason::STATE_CHANGE_REASON_APPLICATION;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_DEVICE_ADMIN:
            ret = StateChangeReason::STATE_CHANGE_REASON_REMOTE;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_TIMEOUT:
            ret = (enabledTimingOutLockScreen_.load() &&
                  (!enabledTimingOutLockScreenCheckLock_.load() || CheckRunningLock(PowerState::INACTIVE))) ?
                StateChangeReason::STATE_CHANGE_REASON_TIMEOUT :
                StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_LID:
            ret = StateChangeReason::STATE_CHANGE_REASON_LID;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_SWITCH:
            ret = StateChangeReason::STATE_CHANGE_REASON_SWITCH;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_POWER_KEY: // fall through
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_SLEEP_KEY:
            ret = StateChangeReason::STATE_CHANGE_REASON_HARD_KEY;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_HDMI:
            ret = StateChangeReason::STATE_CHANGE_REASON_CABLE;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_ACCESSIBILITY:
            ret = StateChangeReason::STATE_CHANGE_REASON_ACCESSIBILITY;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_FORCE_SUSPEND:
            ret = StateChangeReason::STATE_CHANGE_REASON_SYSTEM;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_TP_COVER:
            ret = StateChangeReason::STATE_CHANGE_REASON_TP_COVER;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_EX_SCREEN_INIT:
            ret = StateChangeReason::STATE_CHANGE_REASON_EX_SCREEN_INIT;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_SWITCH_SENSORHUB:
            ret = StateChangeReason::STATE_CHANGE_REASON_SWITCH_SENSORHUB;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_ROLLBACK_HIBERNATE:
            ret = StateChangeReason::STATE_CHANGE_REASON_ROLLBACK_HIBERNATE;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_START_DREAM:
            ret = StateChangeReason::STATE_CHANGE_REASON_START_DREAM;
            break;
        case SuspendDeviceType::SUSPEND_DEVICE_REASON_PEOPLE_LEAVING:
            ret = StateChangeReason::STATE_CHANGE_REASON_PEOPLE_LEAVING;
            break;
        default:
            break;
    }
    POWER_HILOGD(FEATURE_SUSPEND, "StateChangeReason: %{public}u", ret);
    return ret;
}

void PowerStateMachine::AppendDumpInfo(std::string& result, std::string& reason, std::string& time)
{
    result.append("POWER STATE DUMP:\n");
    result.append("Current State: ")
        .append(PowerUtils::GetPowerStateString(GetState()))
        .append("  Reason: ")
        .append(reason)
        .append("  Time: ")
        .append(time)
        .append("\n");

    result.append("ScreenOffTime: Timeout=");
    if (isScreenOffTimeOverride_) {
        result.append((ToString(g_beforeOverrideTime)))
            .append("ms  OverrideTimeout=")
            .append((ToString(GetDisplayOffTime())))
            .append("ms\n");
    } else {
        result.append((ToString(GetDisplayOffTime()))).append("ms\n");
    }

    result.append("DUMP DETAILS:\n");
    result.append("Last Screen On: ").append(ToString(mDeviceState_.screenState.lastOnTime)).append("\n");
    result.append("Last Screen Off: ").append(ToString(mDeviceState_.screenState.lastOffTime)).append("\n");
    result.append("Last SuspendDevice: ").append(ToString(mDeviceState_.lastSuspendDeviceTime)).append("\n");
    result.append("Last WakeupDevice: ").append(ToString(mDeviceState_.lastWakeupDeviceTime)).append("\n");
    result.append("Last Refresh: ").append(ToString(mDeviceState_.lastRefreshActivityTime)).append("\n");

    result.append("DUMP EACH STATES:\n");
    for (auto it = controllerMap_.begin(); it != controllerMap_.end(); it++) {
        result.append("State: ")
            .append(PowerUtils::GetPowerStateString(it->second->GetState()))
            .append("   Reason: ")
            .append(PowerUtils::GetReasonTypeString(it->second->lastReason_).c_str())
            .append("   Time: ")
            .append(ToString(it->second->lastTime_))
            .append("\n")
            .append("   Failure: ")
            .append(PowerUtils::GetReasonTypeString(it->second->failTrigger_).c_str())
            .append("   Reason: ")
            .append(it->second->failReason_)
            .append("   From: ")
            .append(PowerUtils::GetPowerStateString(it->second->failFrom_))
            .append("   Time: ")
            .append(ToString(it->second->failTime_))
            .append("\n\n");
    }
}

void PowerStateMachine::DumpInfo(std::string& result)
{
    std::string reason = "UNKNOWN";
    std::string time = "UNKNOWN";
    auto it = controllerMap_.find(GetState());
    if (it != controllerMap_.end() && it->second != nullptr) {
        reason = ToString(static_cast<uint32_t>(it->second->lastReason_));
        time = ToString(it->second->lastTime_);
    }
    AppendDumpInfo(result, reason, time);
}

bool PowerStateMachine::StateController::NeedNotify(PowerState currentState)
{
#ifdef POWER_MANAGER_ENABLE_FORCE_SLEEP_BROADCAST
    // need notify when SLEEP->SLEEP if force sleeping flag is set
    if (currentState == PowerState::SLEEP && GetState() == PowerState::SLEEP) {
        auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
        auto suspendController = (pms != nullptr ? pms->GetSuspendController() : nullptr);

        if (suspendController == nullptr) {
            POWER_HILOGE(FEATURE_POWER_STATE, "suspendController is nullptr, can't get force sleeping flag");
        } else if (suspendController->GetForceSleepingFlag()) {
            return true;
        }
    }
#endif

    if (currentState == GetState()) {
        return false;
    }
    if (currentState == PowerState::DIM && GetState() == PowerState::AWAKE) {
        return false;
    }
    return true;
}

TransitResult PowerStateMachine::StateController::TransitTo(StateChangeReason reason, bool ignoreLock)
{
    POWER_HILOGD(FEATURE_POWER_STATE, "Start");
    std::shared_ptr<PowerStateMachine> owner = owner_.lock();
    if (owner == nullptr) {
        POWER_HILOGW(FEATURE_POWER_STATE, "owner is nullptr");
        return TransitResult::OTHER_ERR;
    }
    POWER_HILOGI(FEATURE_POWER_STATE,
        "[UL_POWER] Transit from %{public}s to %{public}s for %{public}s ignoreLock=%{public}d",
        PowerUtils::GetPowerStateString(owner->currentState_).c_str(),
        PowerUtils::GetPowerStateString(this->state_).c_str(),
        PowerUtils::GetReasonTypeString(reason).c_str(), ignoreLock);
    MatchState(owner->currentState_, owner->stateAction_->GetDisplayState());
    if (!CheckState()) {
        POWER_HILOGD(FEATURE_POWER_STATE, "Already in state: %{public}d", owner->currentState_);
        RecordFailure(owner->currentState_, reason, TransitResult::ALREADY_IN_STATE);
        return TransitResult::ALREADY_IN_STATE;
    }

    if (reason != StateChangeReason::STATE_CHANGE_REASON_INIT &&
        !owner->CanTransitTo(owner->currentState_, state_, reason)) {
        POWER_HILOGD(FEATURE_POWER_STATE, "Block Transit from %{public}s to %{public}s",
            PowerUtils::GetPowerStateString(owner->currentState_).c_str(),
            PowerUtils::GetPowerStateString(state_).c_str());
        RecordFailure(owner->currentState_, reason, TransitResult::FORBID_TRANSIT);
        return TransitResult::FORBID_TRANSIT;
    }

    if (!ignoreLock && !owner->CheckRunningLock(GetState())) {
        POWER_HILOGD(FEATURE_POWER_STATE, "Running lock block");
        RecordFailure(owner->currentState_, reason, TransitResult::LOCKING);
        return TransitResult::LOCKING;
    }

    if (!owner->HandlePreBrightState(state_, reason)) {
        return TransitResult::PRE_BRIGHT_ERR;
    }

    TransitResult ret = action_(reason);
    if (ret == TransitResult::SUCCESS) {
        bool needNotify = NeedNotify(owner->currentState_);
        lastReason_ = reason;
        lastTime_ = GetTickCount();
        owner->currentState_ = GetState();
        if (needNotify) {
            owner->NotifyPowerStateChanged(owner->currentState_, reason);
        }
    } else if (IsReallyFailed(reason) && (ret != TransitResult::TAKEN_OVER)) {
        RecordFailure(owner->currentState_, reason, ret);
    }

    POWER_HILOGD(FEATURE_POWER_STATE, "Finish, result: %{public}d", ret);
    return ret;
}

bool PowerStateMachine::StateController::CheckState()
{
    std::shared_ptr<PowerStateMachine> owner = owner_.lock();
    if (owner == nullptr) {
        POWER_HILOGW(FEATURE_POWER_STATE, "Owner is nullptr");
        return false;
    }
    auto state = GetState();
    if (state == PowerState::DIM ||
#ifdef POWER_MANAGER_ENABLE_FORCE_SLEEP_BROADCAST
        state == PowerState::SLEEP ||
#endif
        state == PowerState::AWAKE) {
        return true;
    }
    POWER_HILOGD(FEATURE_POWER_STATE, "state: %{public}u, currentState_: %{public}u", state, owner->currentState_);
    return state != owner->currentState_;
}

void PowerStateMachine::StateController::CorrectState(
    PowerState& currentState, PowerState correctState, DisplayState state)
{
    std::string msg = "[UL_POWER] Correct power state errors from ";
    msg.append(PowerUtils::GetPowerStateString(currentState))
        .append(" to ")
        .append(PowerUtils::GetPowerStateString(correctState))
        .append(" due to current display state is ")
        .append(PowerUtils::GetDisplayStateString(state));
    POWER_HILOGW(FEATURE_POWER_STATE, "%{public}s", msg.c_str());
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "STATE_CORRECTION", HiviewDFX::HiSysEvent::EventType::FAULT,
        "ERROR_STATE", static_cast<uint32_t>(currentState), "CORRECTION_STATE", static_cast<uint32_t>(correctState),
        "DISPLAY_STATE", static_cast<uint32_t>(state), "MSG", msg);
#endif
    currentState = correctState;
}

void PowerStateMachine::StateController::MatchState(PowerState& currentState, DisplayState state)
{
    if (GetState() == PowerState::SLEEP || currentState == PowerState::SLEEP || GetState() == PowerState::HIBERNATE ||
        currentState == PowerState::HIBERNATE || GetState() == PowerState::SHUTDOWN ||
        currentState == PowerState::SHUTDOWN) {
        return;
    }

    // Keep the state of display consistent with the state of power
    switch (state) {
        case DisplayState::DISPLAY_OFF:
            if (currentState == PowerState::AWAKE || currentState == PowerState::FREEZE) {
                CorrectState(currentState, PowerState::INACTIVE, state);
            }
            break;
        case DisplayState::DISPLAY_DIM:
            if (currentState == PowerState::INACTIVE || currentState == PowerState::STAND_BY ||
                currentState == PowerState::DOZE) {
                CorrectState(currentState, PowerState::DIM, state);
            }
            break;
        case DisplayState::DISPLAY_ON:
            if (currentState == PowerState::INACTIVE || currentState == PowerState::STAND_BY ||
                currentState == PowerState::DOZE) {
                CorrectState(currentState, PowerState::AWAKE, state);
            }
            break;
        case DisplayState::DISPLAY_SUSPEND:
        case DisplayState::DISPLAY_UNKNOWN:
        default:
            break;
    }
}

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

std::string PowerStateMachine::GetTransitResultString(TransitResult result)
{
    switch (result) {
        case TransitResult::ALREADY_IN_STATE:
            return "Already in the state";
        case TransitResult::LOCKING:
            return "Blocked by running lock";
        case TransitResult::HDI_ERR:
            return "Power HDI error";
        case TransitResult::DISPLAY_ON_ERR:
            return "SetDisplayState(ON) error";
        case TransitResult::DISPLAY_OFF_ERR:
            return "SetDisplayState(OFF) error";
        case TransitResult::FORBID_TRANSIT:
            return "Forbid transit";
        case TransitResult::OTHER_ERR:
            return "Other error";
        default:
            break;
    }
    return "Unknown error";
}

void PowerStateMachine::StateController::RecordFailure(
    PowerState from, StateChangeReason trigger, TransitResult failReason)
{
    failFrom_ = from;
    failTrigger_ = trigger;
    failTime_ = GetTickCount();
    failReason_ = GetTransitResultString(failReason);
    std::string message = "State Transit Failed from ";
    message.append(PowerUtils::GetPowerStateString(failFrom_))
        .append(" to ")
        .append(PowerUtils::GetPowerStateString(GetState()))
        .append(" by ")
        .append(PowerUtils::GetReasonTypeString(failTrigger_).c_str())
        .append("   Reason:")
        .append(failReason_)
        .append("   Time:")
        .append(ToString(failTime_))
        .append("\n");
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    const int logLevel = 2;
    const std::string tag = "TAG_POWER";
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SCREEN", HiviewDFX::HiSysEvent::EventType::FAULT,
        "LOG_LEVEL", logLevel, "TAG", tag, "MESSAGE", message);
    POWER_HILOGI(FEATURE_POWER_STATE, "RecordFailure: %{public}s", message.c_str());
#endif
}

bool PowerStateMachine::StateController::IsReallyFailed(StateChangeReason reason)
{
    if (reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT ||
        reason == StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF) {
        return false;
    }
    return true;
}

bool PowerStateMachine::HandleDuringCall(bool isProximityClose)
{
    // when screen is off or duringcall is false, wakeup or suspend is normal
    if (!isDuringCall_ || !IsScreenOn()) {
        return false;
    }
    Rosen::FoldDisplayMode mode = Rosen::DisplayManagerLite::GetInstance().GetFoldDisplayMode();
    POWER_HILOGI(FEATURE_POWER_STATE, "HandleDuringCall mode:%{public}d, isProximityClose:%{public}d",
        static_cast<int32_t>(mode), isProximityClose);
    if (mode == Rosen::FoldDisplayMode::MAIN && isProximityClose &&
        IsRunningLockEnabled(RunningLockType::RUNNINGLOCK_PROXIMITY_SCREEN_CONTROL)) {
        Rosen::DisplayManagerLite::GetInstance().SetFoldDisplayMode(Rosen::FoldDisplayMode::SUB);
    } else if (mode == Rosen::FoldDisplayMode::SUB && !isProximityClose) {
        Rosen::DisplayManagerLite::GetInstance().SetFoldDisplayMode(Rosen::FoldDisplayMode::MAIN);
    }
    return true;
}

bool PowerStateMachine::IsSwitchOpenByPath()
{
    std::string value = "";
    int32_t ret = SystemSuspendController::GetInstance().GetPowerConfig(LID_STATUS_SCENE_NAME, value);
    if (ret != ERR_OK) {
        POWER_HILOGE(FEATURE_POWER_STATE, "IsSwitchOpenByPath GetPowerConfig failed, ret: %{public}d", ret);
        return IsSwitchOpen();
    }
    int32_t num = 0;
    bool rst = StrToInt(value, num);
    if (rst != true) {
        POWER_HILOGE(FEATURE_POWER_STATE, "IsSwitchOpenByPath StrToInt failed, value: %{public}s", value.c_str());
        return IsSwitchOpen();
    }
    bool status = static_cast<bool>(num);
    POWER_HILOGI(FEATURE_POWER_STATE, "IsSwitchOpenByPath status: %{public}d", status);
    return status;
}

#ifdef POWER_MANAGER_REPORT_SCREENOFF_INVALID
bool PowerStateMachine::ReportScreenOffInvalidEvent(StateChangeReason reason)
{
    if (reason != StateChangeReason::STATE_CHANGE_REASON_HARD_KEY) {
        POWER_HILOGD(FEATURE_POWER_STATE, "ReportScreenOffInvalidEvent fail, reason: %{public}d", reason);
        return false;
    }
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    FFRTTask task = [this] {
        // condition 1: no audiolock
        // condition 2: has screenlock
        if (!IsRunningLockEnabled(RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO)) {
            std::map<std::string, RunningLockInfo> screenOnLockLists;
            auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
            if (pms == nullptr) {
                POWER_HILOGE(FEATURE_POWER_STATE, "ReportScreenOffInvalidEvent fail, Pms is nullptr");
                return;
            }
            pms->QueryRunningLockListsInner(screenOnLockLists);
            for (const auto &it : screenOnLockLists) {
                HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SCREEN_OFF_EXCEPTION",
                    HiviewDFX::HiSysEvent::EventType::FAULT, "EXCEPTION_TYPE", SCREEN_OFF_INVALID,
                    "PID", it.second.pid, "UID", it.second.uid, "BUNDLE_NAME", it.second.bundleName.c_str(),
                    "ABILITY_NAME", "", "WINDOW_ID", 0, "APP_BEHAVIOR", "");
            }
        }
    };
    FFRTUtils::SubmitTask(task);
#endif
    return true;
}

bool PowerStateMachine::ReportAbnormalScreenOffEvent(StateChangeReason reason)
{
    if (reason != StateChangeReason::STATE_CHANGE_REASON_TIMEOUT &&
        reason != StateChangeReason::STATE_CHANGE_REASON_TIMEOUT_NO_SCREEN_LOCK) {
        POWER_HILOGD(FEATURE_POWER_STATE, "ReportAbnormalScreenOffEvent fail, reason: %{public}d", reason);
        return false;
    }
#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
    FFRTTask task = [this] {
        // condition 1: no cast
        if (forceTimingOut_.load()) {
            POWER_HILOGD(FEATURE_POWER_STATE, "ReportAbnormalScreenOffEvent fail, Currently casting");
            return;
        }
        auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
        if (pms == nullptr) {
            POWER_HILOGE(FEATURE_POWER_STATE, "ReportAbnormalScreenOffEvent fail, Pms is nullptr");
            return;
        }
        // condition 2: current visible window is not desktop
        // condition 3: audio stream exist in the window
        std::vector<sptr<Rosen::WindowVisibilityInfo>> infos;
        Rosen::WindowManagerLite::GetInstance().GetVisibilityWindowInfo(infos);
        for (const auto &it: infos) {
            if (it != nullptr && it->visibilityState_ < Rosen::WindowVisibilityState::WINDOW_LAYER_STATE_MAX
                && it->bundleName_.compare(it->abilityName_) != 0 && pms->IsExistAudioStream(it->uid_)) {
                HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SCREEN_OFF_EXCEPTION",
                    HiviewDFX::HiSysEvent::EventType::FAULT, "EXCEPTION_TYPE", SCREEN_OFF_ABNORMAL,
                    "PID", it->pid_, "UID", it->uid_, "BUNDLE_NAME", it->bundleName_.c_str(), "ABILITY_NAME",
                    it->abilityName_.c_str(), "WINDOW_ID", it->windowId_, "APP_BEHAVIOR", "");
            }
        }
    };
    FFRTUtils::SubmitTask(task);
#endif
    return true;
}
#endif

#ifdef POWER_MANAGER_TAKEOVER_SUSPEND
TransitResult PowerStateMachine::TakeOverSuspendAction(StateChangeReason reason)
{
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "pms is nullptr");
        return TransitResult::OTHER_ERR;
    }

    auto suspendController = pms->GetSuspendController();
    if (suspendController == nullptr) {
        POWER_HILOGE(FEATURE_SUSPEND, "suspendController is nullptr");
        return TransitResult::OTHER_ERR;
    }

    bool isTakenOver = suspendController->TriggerTakeOverSuspendCallback(GetSuspendTypeByReason(reason));
    if (isTakenOver) {
        POWER_HILOGE(FEATURE_SUSPEND, "Suspend is taken over by OnTakeOverSuspend callback");
        return TransitResult::TAKEN_OVER;
    }
    return TransitResult::SUCCESS;
}
#endif

#ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
void PowerStateMachine::GetSceneStatusInfo(int8_t& switchOpen, int8_t& chargeConnect, int8_t& externalScreen)
{
    constexpr int8_t INVALID_VALUE = 127;
    switchOpen = INVALID_VALUE;     // 0: switch or lid close, 1: switch or lid open, 127: default
    chargeConnect = INVALID_VALUE;  // 0: DC, 1: AC, 127: default
    externalScreen = INVALID_VALUE; // 0: no external screen, 1: one external screen, 127: default
    auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
    if (pms && pms->IsLidCheckEnable()) {
        switchOpen = static_cast<int8_t>(!PowerMgrService::isInLidMode_);
    } else {
        switchOpen = static_cast<int8_t>(IsSwitchOpen());
    }
#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
    if (pms != nullptr) {
        chargeConnect = static_cast<int8_t>(pms->GetPowerConnectStatus());
    }
#endif
#ifdef POWER_MANAGER_ENABLE_EXTERNAL_SCREEN_MANAGEMENT
    externalScreen = static_cast<int8_t>(GetExternalScreenNumber());
#endif
}

void PowerStateMachine::ReportSuspendStart(int32_t uid, int32_t reason, bool force)
{
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SLEEP_START", HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
        "TRIGGER_EVENT_TYPE", static_cast<int32_t>(reason), "ACTION_EVENT_TYPE", static_cast<int32_t>(force));
    
    int8_t switchOpen = 0;
    int8_t chargeConnect = 0;
    int8_t externalScreen = 0;
    GetSceneStatusInfo(switchOpen, chargeConnect, externalScreen);
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SUSPEND_STATISTIC",
        HiviewDFX::HiSysEvent::EventType::STATISTIC, "FORCE", static_cast<int8_t>(force), "UID", uid, "REASON", reason,
        "SWITCH", switchOpen, "CHARGE", chargeConnect, "EXSCREEN", externalScreen);
}

void PowerStateMachine::ReportWakeupStart(int32_t uid, int32_t reason)
{
    int8_t switchOpen = 0;
    int8_t chargeConnect = 0;
    int8_t externalScreen = 0;
    GetSceneStatusInfo(switchOpen, chargeConnect, externalScreen);
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "WAKEUP_STATISTIC",
        HiviewDFX::HiSysEvent::EventType::STATISTIC, "UID", uid, "REASON", reason, "SWITCH", switchOpen, "CHARGE",
        chargeConnect, "EXSCREEN", externalScreen);
}

void PowerStateMachine::ReportHibernateStart(int32_t uid, const std::string& reason, bool clearMemory)
{
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "HIBERNATE_START",
        HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "CLEAR_MEMORY", static_cast<int32_t>(clearMemory));

    int8_t switchOpen = 0;
    int8_t chargeConnect = 0;
    int8_t externalScreen = 0;
    GetSceneStatusInfo(switchOpen, chargeConnect, externalScreen);
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "HIBERNATE_STATISTIC",
        HiviewDFX::HiSysEvent::EventType::STATISTIC, "CLEAR_MEMORY", static_cast<int8_t>(clearMemory), "START_REASON",
        reason, "START_UID", uid, "SWITCH", switchOpen, "CHARGE", chargeConnect, "EXSCREEN", externalScreen);
}

void PowerStateMachine::ReportHibernatePrepareFailed(HibernatePrepareFailedReason reason)
{
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "HIBERNATE_STATISTIC",
        HiviewDFX::HiSysEvent::EventType::STATISTIC, "PREPARE_FAILED_REASON", static_cast<int32_t>(reason));
}

void PowerStateMachine::ReportShutdownStart(int32_t uid, const std::string& reason, bool isReboot)
{
    int8_t switchOpen = 0;
    int8_t chargeConnect = 0;
    int8_t externalScreen = 0;
    GetSceneStatusInfo(switchOpen, chargeConnect, externalScreen);
    HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "SHUTDOWN_STATISTIC",
        HiviewDFX::HiSysEvent::EventType::STATISTIC, "START_REASON", reason, "START_UID", uid, "SWITCH", switchOpen,
        "CHARGE", chargeConnect, "EXSCREEN", externalScreen, "IS_REBOOT", static_cast<int8_t>(isReboot));
}
#endif

#ifdef POWER_MANAGER_ENABLE_WATCH_CUSTOMIZED_SCREEN_COMMON_EVENT_RULES
bool PowerStateMachine::SetScreenCommonEventRules(StateChangeReason reason)
{
    auto screenCommonEventController = DelayedSingleton<ScreenCommonEventController>::GetInstance();
    if (screenCommonEventController == nullptr) {
        POWER_HILOGE(FEATURE_POWER_STATE, "PowerStateMachine screenCommonEventController is nullptr.");
        return false;
    }
    screenCommonEventController->SetScreenOnCommonEventRules(reason);
    return true;
}
#endif
} // namespace PowerMgr
} // namespace OHOS