Wwangbaidong日志整改
f116b727创建于 3月12日历史提交
/*
 * Copyright (c) 2025 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 "dm_freeze_process.h"

#include "cJSON.h"
#include "datetime_ex.h"
#include "dm_anonymous.h"
#include "dm_device_info.h"
#include "dm_error_type.h"
#include "dm_log.h"

namespace OHOS {
namespace DistributedHardware {
namespace {
constexpr const char* BIND_FAILED_EVENTS_KEY = "bindFailedEvents";
constexpr const char* FREEZE_STATE_KEY = "freezeState";
constexpr const char* START_FREEZE_TIME_KEY = "startFreezeTimeStamp";
constexpr const char* STOP_FREEZE_TIME_KEY = "stopFreezeTimeStamp";
constexpr const char* FAILED_TIMES_STAMPS_KEY = "failedTimeStamps";
constexpr const char* FREEZE_TIMES_STAMPS_KEY = "freezeTimeStamps";
constexpr const char* IS_NEED_FREEZE = "IsNeedFreeze";
constexpr const char* NEED_FREEZE = "0";
constexpr const char* NO_NEED_FREEZE = "1";
constexpr int32_t MAX_CONTINUOUS_BIND_FAILED_NUM = 2;
constexpr int64_t CONTINUEOUS_FAILED_INTERVAL = 6 * 60;
constexpr int64_t DATA_REFRESH_INTERVAL = 20 * 60;
constexpr int64_t NOT_FREEZE_DURATION_SEC = 0;
constexpr int64_t FIRST_FREEZE_DURATION_SEC = 60;
constexpr int64_t SECOND_FREEZE_DURATION_SEC = 3 * 60;
constexpr int64_t THIRD_FREEZE_DURATION_SEC = 5 * 60;
constexpr int64_t MAX_FREEZE_DURATION_SEC = 10 * 60;
constexpr const static char* IS_NEED_FREEZE_WHITE_LIST[] = {
    "CollaborationFwk",
};
constexpr int32_t IS_NEED_FREEZE_WHITE_LIST_NUM = std::size(IS_NEED_FREEZE_WHITE_LIST);
}

DM_IMPLEMENT_SINGLE_INSTANCE(FreezeProcess);

int32_t FreezeProcess::SyncFreezeData()
{
    LOGI("called");
    std::string freezeStatesValue;
    int32_t ret = KVAdapterManager::GetInstance().GetFreezeData(FREEZE_STATE_KEY, freezeStatesValue);
    if (ret != DM_OK) {
        LOGE("Get freeze states data failed, ret: %{public}d", ret);
        return ret;
    }
    DeviceFreezeState freezeStateObj;
    ret = ConvertJsonToDeviceFreezeState(freezeStatesValue, freezeStateObj);
    if (ret != DM_OK) {
        LOGE("ConvertJsonToDeviceFreezeState, ret: %{public}d", ret);
        return ret;
    }
    {
        std::lock_guard<ffrt::mutex> lock(freezeStateCacheMtx_);
        freezeStateCache_ = freezeStateObj;
    }
    std::string bindFailedEventsValue;
    ret = KVAdapterManager::GetInstance().GetFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsValue);
    if (ret != DM_OK) {
        LOGE("Get bind failed events data failed, ret: %{public}d", ret);
        return ret;
    }
    BindFailedEvents bindFailedEventsObj;
    ret = ConvertJsonToBindFailedEvents(bindFailedEventsValue, bindFailedEventsObj);
    if (ret != DM_OK) {
        LOGE("ConvertJsonToBindFailedEvents, ret: %{public}d", ret);
        return ret;
    }
    std::lock_guard<ffrt::mutex> lock(bindFailedEventsCacheMtx_);
    bindFailedEventsCache_ = bindFailedEventsObj;
    LOGI("Sync freeze data success");
    return DM_OK;
}

int32_t FreezeProcess::ConvertJsonToDeviceFreezeState(const std::string &result, DeviceFreezeState &freezeStateObj)
{
    if (result.empty()) {
        LOGE("result is empty");
        return ERR_DM_FAILED;
    }
    JsonObject resultJson(result);
    if (resultJson.IsDiscarded()) {
        LOGE("resultJson parse failed");
        return ERR_DM_FAILED;
    }
    if (IsInt64(resultJson, START_FREEZE_TIME_KEY)) {
        freezeStateObj.startFreezeTimeStamp = resultJson[START_FREEZE_TIME_KEY].Get<int64_t>();
    }
    if (IsInt64(resultJson, STOP_FREEZE_TIME_KEY)) {
        freezeStateObj.stopFreezeTimeStamp = resultJson[STOP_FREEZE_TIME_KEY].Get<int64_t>();
    }
    LOGI("success");
    return DM_OK;
}

int32_t FreezeProcess::ConvertJsonToBindFailedEvents(const std::string &result, BindFailedEvents &bindFailedEventsObj)
{
    if (result.empty()) {
        LOGE("result is empty");
        return ERR_DM_FAILED;
    }
    JsonObject resultJson(result);
    if (resultJson.IsDiscarded()) {
        LOGE("resultJson parse failed");
        return ERR_DM_FAILED;
    }
    if (IsArray(resultJson, FAILED_TIMES_STAMPS_KEY)) {
        std::vector<int64_t> failedTimeStampsTmp;
        resultJson[FAILED_TIMES_STAMPS_KEY].Get(failedTimeStampsTmp);
        bindFailedEventsObj.failedTimeStamps = failedTimeStampsTmp;
    }
    if (IsArray(resultJson, FREEZE_TIMES_STAMPS_KEY)) {
        std::vector<int64_t> freezeTimeStampsTmp;
        resultJson[FREEZE_TIMES_STAMPS_KEY].Get(freezeTimeStampsTmp);
        bindFailedEventsObj.freezeTimeStamps = freezeTimeStampsTmp;
    }
    LOGI("success");
    return DM_OK;
}

bool FreezeProcess::IsFrozen(int64_t &remainingFrozenTime)
{
    {
        std::lock_guard<ffrt::mutex> lock(isSyncedMtx_);
        if (!isSynced_) {
            SyncFreezeData();
            isSynced_ = true;
        }
    }
    int64_t stopFreezeTimeStamp = 0;
    {
        std::lock_guard<ffrt::mutex> lock(freezeStateCacheMtx_);
        if (bindFailedEventsCache_.IsEmpty()) {
            LOGI("bindFailedEventsCache is empty");
            return false;
        }
        stopFreezeTimeStamp = freezeStateCache_.stopFreezeTimeStamp;
    }
    int64_t nowTime = GetSecondsSince1970ToNow();
    bool isFrozen = nowTime > stopFreezeTimeStamp ? false : true;
    if (isFrozen) {
        remainingFrozenTime = stopFreezeTimeStamp - nowTime;
    }
    if (CleanFreezeRecord(nowTime) != DM_OK) {
        LOGE("CleanFreezeRecord failed");
    }
    return isFrozen;
}

int32_t FreezeProcess::CleanFreezeRecord(int64_t nowTime)
{
    int64_t reservedDataTimeStamp = nowTime - DATA_REFRESH_INTERVAL;
    if (CleanBindFailedEvents(reservedDataTimeStamp) != DM_OK) {
        LOGE("CleanBindFailedEvents failed");
        return ERR_DM_FAILED;
    }
    if (CleanFreezeState(reservedDataTimeStamp) != DM_OK) {
        LOGE("CleanFreezeState failed");
        return ERR_DM_FAILED;
    }
    LOGI("success");
    return DM_OK;
}

int32_t FreezeProcess::CleanBindFailedEvents(int64_t reservedDataTimeStamp)
{
    std::lock_guard<ffrt::mutex> lock(bindFailedEventsCacheMtx_);
    if (bindFailedEventsCache_.IsEmpty()) {
        LOGI("bindFailedEventsCache is empty, no need to clean");
        return DM_OK;
    }
    BindFailedEvents bindFailedEventsTmp = bindFailedEventsCache_;
    int32_t needCleanBindFailedStampNum = std::count_if(bindFailedEventsTmp.failedTimeStamps.begin(),
        bindFailedEventsTmp.failedTimeStamps.end(),
        [reservedDataTimeStamp](int64_t v) { return v < reservedDataTimeStamp; });
    if (needCleanBindFailedStampNum == 0) {
        LOGI("no stamp is before 20mins, no need to clean");
        return DM_OK;
    }
    bindFailedEventsTmp.failedTimeStamps.erase(
        std::remove_if(bindFailedEventsTmp.failedTimeStamps.begin(),
            bindFailedEventsTmp.failedTimeStamps.end(),
            [reservedDataTimeStamp](int64_t n) { return n < reservedDataTimeStamp; }),
        bindFailedEventsTmp.failedTimeStamps.end());
    bindFailedEventsTmp.freezeTimeStamps.erase(
        std::remove_if(bindFailedEventsTmp.freezeTimeStamps.begin(),
            bindFailedEventsTmp.freezeTimeStamps.end(),
            [reservedDataTimeStamp](int64_t n) { return n < reservedDataTimeStamp; }),
        bindFailedEventsTmp.freezeTimeStamps.end());
    std::string valueStr = "";
    ConvertBindFailedEventsToJson(bindFailedEventsTmp, valueStr);
    if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, valueStr) != DM_OK) {
        LOGE("within 20mins failed");
        return ERR_DM_FAILED;
    }
    bindFailedEventsCache_ = bindFailedEventsTmp;
    LOGI("success");
    return DM_OK;
}

int32_t FreezeProcess::CleanFreezeState(int64_t reservedDataTimeStamp)
{
    std::lock_guard<ffrt::mutex> lock(freezeStateCacheMtx_);
    if (freezeStateCache_.IsEmpty()) {
        LOGI("freezeStateCache is empty, no need to clean");
        return DM_OK;
    }
    if (freezeStateCache_.startFreezeTimeStamp >= reservedDataTimeStamp) {
        LOGI("startFreezeTimeStamp is in 20 mins, no need to clean");
        return DM_OK;
    }
    if (KVAdapterManager::GetInstance().DeleteFreezeData(FREEZE_STATE_KEY) != DM_OK) {
        LOGE("delete freeze states data within 20mins failed");
        return ERR_DM_FAILED;
    }
    freezeStateCache_.Reset();
    LOGI("success");
    return DM_OK;
}

void FreezeProcess::ConvertBindFailedEventsToJson(const BindFailedEvents &value, std::string &result)
{
    JsonObject jsonObj;
    jsonObj[FAILED_TIMES_STAMPS_KEY] = value.failedTimeStamps;
    jsonObj[FREEZE_TIMES_STAMPS_KEY] = value.freezeTimeStamps;
    result = jsonObj.Dump();
}

void FreezeProcess::ConvertDeviceFreezeStateToJson(const DeviceFreezeState &value, std::string &result)
{
    JsonObject jsonObj;
    jsonObj[START_FREEZE_TIME_KEY] = value.startFreezeTimeStamp;
    jsonObj[STOP_FREEZE_TIME_KEY] = value.stopFreezeTimeStamp;
    result = jsonObj.Dump();
}

int32_t FreezeProcess::DeleteFreezeRecord()
{
    if (KVAdapterManager::GetInstance().DeleteFreezeData(FREEZE_STATE_KEY) != DM_OK) {
        LOGE("delete freezeStates data failed");
        return ERR_DM_FAILED;
    }
    {
        std::lock_guard<ffrt::mutex> lock(freezeStateCacheMtx_);
        freezeStateCache_.Reset();
    }
    if (KVAdapterManager::GetInstance().DeleteFreezeData(BIND_FAILED_EVENTS_KEY) != DM_OK) {
        LOGE("delete bindFailedEvents data failed");
        return ERR_DM_FAILED;
    }
    std::lock_guard<ffrt::mutex> lock(bindFailedEventsCacheMtx_);
    bindFailedEventsCache_.Reset();
    return DM_OK;
}

int32_t FreezeProcess::UpdateFreezeRecord()
{
    int64_t nowTime = GetSecondsSince1970ToNow();
    std::lock_guard<ffrt::mutex> lock(bindFailedEventsCacheMtx_);
    BindFailedEvents bindFailedEventsTmp = bindFailedEventsCache_;
    int64_t lastFreezeTimeStamps = 0;
    if (!bindFailedEventsTmp.freezeTimeStamps.empty()) {
        lastFreezeTimeStamps = bindFailedEventsTmp.freezeTimeStamps.back();
    }
    int32_t continueBindFailedNum = std::count_if(bindFailedEventsTmp.failedTimeStamps.begin(),
        bindFailedEventsTmp.failedTimeStamps.end(),
        [nowTime, lastFreezeTimeStamps](
            int64_t v) { return v > nowTime - CONTINUEOUS_FAILED_INTERVAL && v > lastFreezeTimeStamps; });
    if (continueBindFailedNum < MAX_CONTINUOUS_BIND_FAILED_NUM) {
        bindFailedEventsTmp.failedTimeStamps.push_back(nowTime);
        std::string bindFailedEventsStr = "";
        ConvertBindFailedEventsToJson(bindFailedEventsTmp, bindFailedEventsStr);
        if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsStr) != DM_OK) {
            LOGE("UpdateBindFailedEvents failed");
            return ERR_DM_FAILED;
        }
        bindFailedEventsCache_ = bindFailedEventsTmp;
        return DM_OK;
    }
    bindFailedEventsTmp.failedTimeStamps.push_back(nowTime);
    bindFailedEventsTmp.freezeTimeStamps.push_back(nowTime);
    std::string bindFailedEventsStr = "";
    ConvertBindFailedEventsToJson(bindFailedEventsTmp, bindFailedEventsStr);
    if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsStr) != DM_OK) {
        LOGE("UpdateBindFailedEvents failed");
        return ERR_DM_FAILED;
    }
    bindFailedEventsCache_ = bindFailedEventsTmp;
    return UpdateFreezeState(nowTime);
}

int32_t FreezeProcess::UpdateFreezeState(int64_t nowTime)
{
    std::lock_guard<ffrt::mutex> lock(freezeStateCacheMtx_);
    DeviceFreezeState freezeStateTmp = freezeStateCache_;
    int64_t nextFreezeTime = 0;
    CalculateNextFreezeTime(freezeStateTmp.stopFreezeTimeStamp - freezeStateTmp.startFreezeTimeStamp, nextFreezeTime);
    freezeStateTmp.startFreezeTimeStamp = nowTime;
    freezeStateTmp.stopFreezeTimeStamp = nowTime + nextFreezeTime;
    std::string freezeStateStr = "";
    ConvertDeviceFreezeStateToJson(freezeStateTmp, freezeStateStr);
    if (KVAdapterManager::GetInstance().PutFreezeData(FREEZE_STATE_KEY, freezeStateStr) != DM_OK) {
        LOGE("PutFreezeData failed");
        return ERR_DM_FAILED;
    }
    freezeStateCache_ = freezeStateTmp;
    return DM_OK;
}

void FreezeProcess::CalculateNextFreezeTime(int64_t nowFreezeTime, int64_t &nextFreezeTime)
{
    switch (nowFreezeTime) {
        case NOT_FREEZE_DURATION_SEC:
            nextFreezeTime = FIRST_FREEZE_DURATION_SEC;
            break;
        case FIRST_FREEZE_DURATION_SEC:
            nextFreezeTime = SECOND_FREEZE_DURATION_SEC;
            break;
        case SECOND_FREEZE_DURATION_SEC:
            nextFreezeTime = THIRD_FREEZE_DURATION_SEC;
            break;
        default:
            nextFreezeTime = MAX_FREEZE_DURATION_SEC;
            break;
    }
}

bool FreezeProcess::IsNeedFreeze(std::shared_ptr<DmAuthContext> context)
{
    LOGI("called");
    bool isNeedFreeze = true;
    if (context == nullptr) {
        LOGE("context is null");
        return isNeedFreeze;
    }
    if (!IsInWhiteList(context->accessee.bundleName)) {
        LOGE("not in white list");
        return isNeedFreeze;
    }
    OHOS::DistributedDeviceProfile::LocalServiceInfo srvInfo;
    auto ret = DeviceProfileConnector::GetInstance().GetLocalServiceInfoByBundleNameAndPinExchangeType(
        context->accessee.pkgName, context->authType, srvInfo);
    if (ret != DM_OK) {
        LOGE("ServiceInfo not found");
        return isNeedFreeze;
    }
    std::string extraInfo = srvInfo.GetExtraInfo();
    if (extraInfo.empty()) {
        LOGE("no extraInfo");
        return isNeedFreeze;
    }
    JsonObject jsonObj;
    jsonObj.Parse(extraInfo);
    if (jsonObj.IsDiscarded()) {
        LOGE("extraInfo invalid");
        return isNeedFreeze;
    }
    std::string isNeedFreezeStr;
    if (IsString(jsonObj, IS_NEED_FREEZE)) {
        isNeedFreezeStr = jsonObj[IS_NEED_FREEZE].Get<std::string>();
        LOGI("isNeedFreezeStr: %{public}s.", isNeedFreezeStr.c_str());
    }
    if (isNeedFreezeStr == NEED_FREEZE || isNeedFreezeStr == NO_NEED_FREEZE) {
        isNeedFreeze = std::atoi(isNeedFreezeStr.c_str());
    }
    LOGI("isNeedFreeze: %{public}d.", isNeedFreeze);
    return isNeedFreeze;
}

bool FreezeProcess::IsInWhiteList(const std::string &pkgName)
{
    if (pkgName.empty()) {
        LOGE("pkgName is empty");
        return false;
    }
    uint16_t index = 0;
    for (; index < IS_NEED_FREEZE_WHITE_LIST_NUM; ++index) {
        std::string tmp = IS_NEED_FREEZE_WHITE_LIST[index];
        if (pkgName == tmp) {
            return true;
        }
    }
    return false;
}
} // namespace DistributedHardware
} // namespace OHOS