199552fe9Sopenharmony_ci/*
299552fe9Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
399552fe9Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
499552fe9Sopenharmony_ci * you may not use this file except in compliance with the License.
599552fe9Sopenharmony_ci * You may obtain a copy of the License at
699552fe9Sopenharmony_ci *
799552fe9Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
899552fe9Sopenharmony_ci *
999552fe9Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1099552fe9Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1199552fe9Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1299552fe9Sopenharmony_ci * See the License for the specific language governing permissions and
1399552fe9Sopenharmony_ci * limitations under the License.
1499552fe9Sopenharmony_ci */
1599552fe9Sopenharmony_ci
1699552fe9Sopenharmony_ci#include "time_provider.h"
1799552fe9Sopenharmony_ci
1899552fe9Sopenharmony_ci#include <random>
1999552fe9Sopenharmony_ci#include "time_service_client.h"
2099552fe9Sopenharmony_ci#include "timed_task.h"
2199552fe9Sopenharmony_ci#include "standby_service_log.h"
2299552fe9Sopenharmony_ci#include "standby_config_manager.h"
2399552fe9Sopenharmony_ci#ifdef STANDBY_POWER_MANAGER_ENABLE
2499552fe9Sopenharmony_ci#include "power_mode_info.h"
2599552fe9Sopenharmony_ci#include "power_mgr_client.h"
2699552fe9Sopenharmony_ci#endif
2799552fe9Sopenharmony_ci
2899552fe9Sopenharmony_cinamespace OHOS {
2999552fe9Sopenharmony_cinamespace DevStandbyMgr {
3099552fe9Sopenharmony_cinamespace {
3199552fe9Sopenharmony_ci    constexpr int32_t NIGHT_ENTRANCE_HOUR = 23;
3299552fe9Sopenharmony_ci    constexpr int32_t NIGHT_ENTRANCE_MIN = 45;
3399552fe9Sopenharmony_ci    constexpr int32_t DAY_ENTRANCE_HOUR = 6;
3499552fe9Sopenharmony_ci    constexpr int32_t DAY_ENTRANCE_MIN = 0;
3599552fe9Sopenharmony_ci    constexpr int32_t TWENTY_MIN_ENTRANCE_MIN = 20;
3699552fe9Sopenharmony_ci    constexpr int32_t QUARTER_MIN_ENTRANCE_MIN = 15;
3799552fe9Sopenharmony_ci    constexpr int32_t TEN_MIN_ENTRANCE_MIN = 10;
3899552fe9Sopenharmony_ci    constexpr int32_t NIGHT_TWENTY_TWO_CLOCK = 22;
3999552fe9Sopenharmony_ci    constexpr int32_t NIGHT_TWENTY_THREE_CLOCK = 23;
4099552fe9Sopenharmony_ci    constexpr int32_t NIGHT_FIVE_CLOCK = 5;
4199552fe9Sopenharmony_ci    constexpr int32_t THREE_QUARTERS = 45;
4299552fe9Sopenharmony_ci#ifdef STANDBY_POWER_MANAGER_ENABLE
4399552fe9Sopenharmony_ci    constexpr int32_t SAVE_MODE_ENTRANCE_MIN = 1;
4499552fe9Sopenharmony_ci#endif
4599552fe9Sopenharmony_ci}
4699552fe9Sopenharmony_ci
4799552fe9Sopenharmony_cibool TimeProvider::ConvertTimeStampToLocalTime(int64_t curTimeStamp, struct tm& curLocalTime)
4899552fe9Sopenharmony_ci{
4999552fe9Sopenharmony_ci    auto res = localtime_r(&curTimeStamp, &curLocalTime);
5099552fe9Sopenharmony_ci    if (res == nullptr) {
5199552fe9Sopenharmony_ci        STANDBYSERVICE_LOGE("localtime_r failed, can not get valid local time");
5299552fe9Sopenharmony_ci        return false;
5399552fe9Sopenharmony_ci    }
5499552fe9Sopenharmony_ci    return true;
5599552fe9Sopenharmony_ci}
5699552fe9Sopenharmony_ci
5799552fe9Sopenharmony_ciuint32_t TimeProvider::GetCondition(int64_t afterNextSeconds)
5899552fe9Sopenharmony_ci{
5999552fe9Sopenharmony_ci    int64_t curSecTimeStamp = MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs() / MSEC_PER_SEC;
6099552fe9Sopenharmony_ci    struct tm curLocalTime {};
6199552fe9Sopenharmony_ci    curSecTimeStamp += afterNextSeconds;
6299552fe9Sopenharmony_ci    if (!ConvertTimeStampToLocalTime(curSecTimeStamp, curLocalTime)) {
6399552fe9Sopenharmony_ci        STANDBYSERVICE_LOGE("convert time stamp to local time failed");
6499552fe9Sopenharmony_ci        return ConditionType::DAY_STANDBY;
6599552fe9Sopenharmony_ci    }
6699552fe9Sopenharmony_ci    STANDBYSERVICE_LOGD("current local time info: %{public}02d:%{public}02d:%{public}02d", curLocalTime.tm_hour,
6799552fe9Sopenharmony_ci        curLocalTime.tm_min, curLocalTime.tm_sec);
6899552fe9Sopenharmony_ci    if ((curLocalTime.tm_hour < NIGHT_ENTRANCE_HOUR || curLocalTime.tm_min < NIGHT_ENTRANCE_MIN) &&
6999552fe9Sopenharmony_ci        (curLocalTime.tm_hour >= DAY_ENTRANCE_HOUR)) {
7099552fe9Sopenharmony_ci        return ConditionType::DAY_STANDBY;
7199552fe9Sopenharmony_ci    }
7299552fe9Sopenharmony_ci    return ConditionType::NIGHT_STANDBY;
7399552fe9Sopenharmony_ci}
7499552fe9Sopenharmony_ci
7599552fe9Sopenharmony_cibool TimeProvider::TimeDiffToDayNightSwitch(int64_t& timeDiff)
7699552fe9Sopenharmony_ci{
7799552fe9Sopenharmony_ci    int64_t curSecTimeStamp = MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs() / MSEC_PER_SEC;
7899552fe9Sopenharmony_ci    bool res {false};
7999552fe9Sopenharmony_ci    STANDBYSERVICE_LOGD("condition is %{public}u", GetCondition());
8099552fe9Sopenharmony_ci    if (GetCondition() == ConditionType::NIGHT_STANDBY) {
8199552fe9Sopenharmony_ci        res = DiffToFixedClock(curSecTimeStamp, DAY_ENTRANCE_HOUR, DAY_ENTRANCE_MIN, timeDiff);
8299552fe9Sopenharmony_ci    } else {
8399552fe9Sopenharmony_ci        res = DiffToFixedClock(curSecTimeStamp, NIGHT_ENTRANCE_HOUR, NIGHT_ENTRANCE_MIN, timeDiff);
8499552fe9Sopenharmony_ci    }
8599552fe9Sopenharmony_ci    return res;
8699552fe9Sopenharmony_ci}
8799552fe9Sopenharmony_ci
8899552fe9Sopenharmony_cibool TimeProvider::DiffToFixedClock(int64_t curTimeStamp, int32_t tmHour, int32_t tmMin, int64_t& timeDiff)
8999552fe9Sopenharmony_ci{
9099552fe9Sopenharmony_ci    struct tm curUTCTime {};
9199552fe9Sopenharmony_ci    auto res = gmtime_r(&curTimeStamp, &curUTCTime);
9299552fe9Sopenharmony_ci    if (res == nullptr) {
9399552fe9Sopenharmony_ci        STANDBYSERVICE_LOGE("gmtime_r failed, can not get valid utc time");
9499552fe9Sopenharmony_ci        return false;
9599552fe9Sopenharmony_ci    }
9699552fe9Sopenharmony_ci    STANDBYSERVICE_LOGD("current utc time info: %{public}02d:%{public}02d:%{public}02d", curUTCTime.tm_hour,
9799552fe9Sopenharmony_ci        curUTCTime.tm_min, curUTCTime.tm_sec);
9899552fe9Sopenharmony_ci    struct tm targetUTCTime = curUTCTime;
9999552fe9Sopenharmony_ci    targetUTCTime.tm_hour = tmHour;
10099552fe9Sopenharmony_ci    targetUTCTime.tm_min = tmMin;
10199552fe9Sopenharmony_ci    targetUTCTime.tm_sec = 0;
10299552fe9Sopenharmony_ci    STANDBYSERVICE_LOGD("target utc time info: %{public}02d:%{public}02d:%{public}02d", targetUTCTime.tm_hour,
10399552fe9Sopenharmony_ci        targetUTCTime.tm_min, targetUTCTime.tm_sec);
10499552fe9Sopenharmony_ci    timeDiff = std::mktime(&targetUTCTime) - curTimeStamp;
10599552fe9Sopenharmony_ci    if (timeDiff < 0) {
10699552fe9Sopenharmony_ci        timeDiff += SEC_PER_DAY;
10799552fe9Sopenharmony_ci    }
10899552fe9Sopenharmony_ci    timeDiff = timeDiff * MSEC_PER_SEC;
10999552fe9Sopenharmony_ci    return true;
11099552fe9Sopenharmony_ci}
11199552fe9Sopenharmony_ci
11299552fe9Sopenharmony_ciint64_t TimeProvider::GetNapTimeOut()
11399552fe9Sopenharmony_ci{
11499552fe9Sopenharmony_ci    int64_t curSecTimeStamp = MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs() / MSEC_PER_SEC;
11599552fe9Sopenharmony_ci    int32_t napTimeOut = TWENTY_MIN_ENTRANCE_MIN;
11699552fe9Sopenharmony_ci    struct tm curLocalTime {};
11799552fe9Sopenharmony_ci#ifdef STANDBY_POWER_MANAGER_ENABLE
11899552fe9Sopenharmony_ci    if (IsPowerSaveMode()) {
11999552fe9Sopenharmony_ci        return SAVE_MODE_ENTRANCE_MIN * MSEC_PER_MIN;
12099552fe9Sopenharmony_ci    }
12199552fe9Sopenharmony_ci#endif
12299552fe9Sopenharmony_ci    if (!ConvertTimeStampToLocalTime(curSecTimeStamp, curLocalTime)) {
12399552fe9Sopenharmony_ci        return napTimeOut * MSEC_PER_MIN;
12499552fe9Sopenharmony_ci    }
12599552fe9Sopenharmony_ci    if (curLocalTime.tm_hour == NIGHT_TWENTY_TWO_CLOCK) {
12699552fe9Sopenharmony_ci        napTimeOut = QUARTER_MIN_ENTRANCE_MIN;
12799552fe9Sopenharmony_ci    } else if (curLocalTime.tm_hour == NIGHT_TWENTY_THREE_CLOCK && curLocalTime.tm_min < THREE_QUARTERS) {
12899552fe9Sopenharmony_ci        napTimeOut = QUARTER_MIN_ENTRANCE_MIN;
12999552fe9Sopenharmony_ci    } else if (curLocalTime.tm_hour >= NIGHT_TWENTY_THREE_CLOCK || curLocalTime.tm_hour < NIGHT_FIVE_CLOCK ||
13099552fe9Sopenharmony_ci        (curLocalTime.tm_hour == NIGHT_FIVE_CLOCK && curLocalTime.tm_min < THREE_QUARTERS)) {
13199552fe9Sopenharmony_ci        napTimeOut = TEN_MIN_ENTRANCE_MIN;
13299552fe9Sopenharmony_ci    }
13399552fe9Sopenharmony_ci    return napTimeOut * MSEC_PER_MIN;
13499552fe9Sopenharmony_ci}
13599552fe9Sopenharmony_ci
13699552fe9Sopenharmony_ci#ifdef STANDBY_POWER_MANAGER_ENABLE
13799552fe9Sopenharmony_cibool TimeProvider::IsPowerSaveMode()
13899552fe9Sopenharmony_ci{
13999552fe9Sopenharmony_ci    PowerMgr::PowerMode mode = PowerMgr::PowerMgrClient::GetInstance().GetDeviceMode();
14099552fe9Sopenharmony_ci    return (mode == PowerMgr::PowerMode::POWER_SAVE_MODE || mode == PowerMgr::PowerMode::EXTREME_POWER_SAVE_MODE);
14199552fe9Sopenharmony_ci}
14299552fe9Sopenharmony_ci#endif
14399552fe9Sopenharmony_ci
14499552fe9Sopenharmony_ciint32_t TimeProvider::GetRandomDelay(int32_t low, int32_t high)
14599552fe9Sopenharmony_ci{
14699552fe9Sopenharmony_ci    std::random_device rd;
14799552fe9Sopenharmony_ci    std::mt19937 gen(rd());
14899552fe9Sopenharmony_ci    std::uniform_int_distribution<> dist(low, high);
14999552fe9Sopenharmony_ci    return dist(gen);
15099552fe9Sopenharmony_ci}
15199552fe9Sopenharmony_ci}  // namespace DevStandbyMgr
15299552fe9Sopenharmony_ci}  // namespace OHOS
15399552fe9Sopenharmony_ci
154