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

#include <pthread.h>

#include "dm_anonymous.h"
#include "dm_constants.h"
#include "dm_crypto.h"
#include "dm_device_info.h"
#include "dm_log.h"
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
#include "deviceprofile_connector.h"
#endif

namespace OHOS {
namespace DistributedHardware {
const uint32_t DM_EVENT_QUEUE_CAPACITY = 20;
const uint32_t DM_EVENT_WAIT_TIMEOUT = 2;
constexpr const char* THREAD_LOOP = "ThreadLoop";
constexpr const char* STATE_TIMER_PREFIX = "deviceManagerTimer:stateTimer_";
constexpr const char* FILED_AUTHORIZED_APP_LIST = "authorizedAppList";
const uint32_t AUTH_ONCE_STATE_TIMER_MAX = 500;
DmDeviceStateManager::DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,
    std::shared_ptr<IDeviceManagerServiceListener> listener, std::shared_ptr<HiChainConnector> hiChainConnector,
    std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)
    : softbusConnector_(softbusConnector), listener_(listener), hiChainConnector_(hiChainConnector),
    hiChainAuthConnector_(hiChainAuthConnector)
{
    decisionSoName_ = "libdevicemanagerext_decision.z.so";
    StartEventThread();
    LOGI("constructor");
}

DmDeviceStateManager::~DmDeviceStateManager()
{
    LOGI("destructor");
    softbusConnector_->UnRegisterSoftbusStateCallback();
    StopEventThread();
}

int32_t DmDeviceStateManager::RegisterSoftbusStateCallback()
{
    if (softbusConnector_ != nullptr) {
        return softbusConnector_->RegisterSoftbusStateCallback(shared_from_this());
    }
    return DM_OK;
}

void DmDeviceStateManager::SaveOnlineDeviceInfo(const DmDeviceInfo &info)
{
    LOGI("begin, deviceId = %{public}s", GetAnonyString(std::string(info.deviceId)).c_str());
    std::string udid;
    if (SoftbusConnector::GetUdidByNetworkId(info.networkId, udid) == DM_OK) {
        std::string uuid;
        DmDeviceInfo saveInfo = info;
        SoftbusConnector::GetUuidByNetworkId(info.networkId, uuid);
        {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
            std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
            std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
            remoteDeviceInfos_[uuid] = saveInfo;
            stateDeviceInfos_[udid] = saveInfo;
        }
        LOGI("complete, networkId = %{public}s, udid = %{public}s, uuid = %{public}s",
             GetAnonyString(std::string(info.networkId)).c_str(),
             GetAnonyString(udid).c_str(), GetAnonyString(uuid).c_str());
    }
}

void DmDeviceStateManager::DeleteOfflineDeviceInfo(const DmDeviceInfo &info)
{
    LOGI("begin, deviceId = %{public}s", GetAnonyString(std::string(info.deviceId)).c_str());
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        std::string deviceId = std::string(info.deviceId);
        for (auto iter: remoteDeviceInfos_) {
            if (std::string(iter.second.deviceId) == deviceId) {
                remoteDeviceInfos_.erase(iter.first);
                LOGI("Delete remoteDeviceInfos complete");
                break;
            }
        }
        for (auto iter: stateDeviceInfos_) {
            if (std::string(iter.second.deviceId) == deviceId) {
                stateDeviceInfos_.erase(iter.first);
                LOGI("Delete stateDeviceInfos complete");
                break;
            }
        }
    }
    std::lock_guard<std::mutex> mutexLock(notifyEventInfosMutex_);
    std::string deviceId = std::string(info.deviceId);
    for (auto iter: notifyEventInfos_) {
        if (std::string(iter.second.deviceId) == deviceId) {
            notifyEventInfos_.erase(iter.first);
            LOGI("Delete notifyEventInfos_ complete");
            break;
        }
    }
}

void DmDeviceStateManager::OnDeviceOnline(std::string deviceId, int32_t authForm)
{
    std::string uuid = "";
    DmDeviceInfo devInfo = softbusConnector_->GetDeviceInfoByDeviceId(deviceId, uuid);
    if (devInfo.deviceId[0] == '\0') {
        LOGE("deviceId is empty.");
        return;
    }
    LOGI("deviceId: %{public}s,  uuid: %{public}s", GetAnonyString(deviceId).c_str(), GetAnonyString(uuid).c_str());
    devInfo.authForm = static_cast<DmAuthForm>(authForm);
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        if (stateDeviceInfos_.find(deviceId) == stateDeviceInfos_.end()) {
            stateDeviceInfos_[deviceId] = devInfo;
        }
        if (remoteDeviceInfos_.find(uuid) == remoteDeviceInfos_.end()) {
            remoteDeviceInfos_[uuid] = devInfo;
        }
    }
    std::vector<ProcessInfo> processInfoVec = softbusConnector_->GetProcessInfo();
    ProcessDeviceStateChange(DEVICE_STATE_ONLINE, devInfo, processInfoVec, true);
    softbusConnector_->ClearProcessInfo();
}

void DmDeviceStateManager::OnDeviceOffline(std::string deviceId, const bool isOnline)
{
    LOGI("deviceId = %{public}s", GetAnonyString(deviceId).c_str());
    DmDeviceInfo devInfo;
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        if (stateDeviceInfos_.find(deviceId) == stateDeviceInfos_.end()) {
            LOGE("not find deviceId");
            return;
        }
        devInfo = stateDeviceInfos_[deviceId];
    }
    std::vector<ProcessInfo> processInfoVec = softbusConnector_->GetProcessInfo();
    ProcessDeviceStateChange(DEVICE_STATE_OFFLINE, devInfo, processInfoVec, isOnline);
    softbusConnector_->ClearProcessInfo();
}
void DmDeviceStateManager::HandleDeviceStatusChange(DmDeviceState devState, DmDeviceInfo &devInfo,
    std::vector<ProcessInfo> &processInfoVec, const std::string &peerUdid, const bool isOnline)
{
    LOGI("Handle device status change: devState=%{public}d, deviceId=%{public}s.", devState,
        GetAnonyString(devInfo.deviceId).c_str());
    switch (devState) {
        case DEVICE_STATE_ONLINE:
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
            RegisterOffLineTimer(devInfo);
#endif
            SaveOnlineDeviceInfo(devInfo);
            // need implement in the future
            // DmDistributedHardwareLoad::GetInstance().LoadDistributedHardwareFwk();
            ProcessDeviceStateChange(devState, devInfo, processInfoVec, isOnline);
            break;
        case DEVICE_STATE_OFFLINE:
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
            StartOffLineTimer(peerUdid);
#endif
            DeleteOfflineDeviceInfo(devInfo);
            if (softbusConnector_ != nullptr) {
                std::string udid;
                softbusConnector_->GetUdidByNetworkId(devInfo.networkId, udid);
                softbusConnector_->EraseUdidFromMap(udid);
            }
            ProcessDeviceStateChange(devState, devInfo, processInfoVec, isOnline);
            break;
        case DEVICE_INFO_CHANGED:
            ChangeDeviceInfo(devInfo);
            ProcessDeviceStateChange(devState, devInfo, processInfoVec, isOnline);
            break;
        default:
            LOGE("unknown device state = %{public}d", devState);
            break;
    }
}

#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
void DmDeviceStateManager::ProcessDeviceStateChange(const DmDeviceState devState, const DmDeviceInfo &devInfo,
    std::vector<ProcessInfo> &processInfoVec, const bool isOnline)
{
    LOGI("begin, devState = %{public}d networkId: %{public}s.", devState, GetAnonyString(devInfo.networkId).c_str());
    std::unordered_set<int64_t> remoteTokenIds;
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    std::string localUdid(localDeviceId);
    CHECK_NULL_VOID(softbusConnector_);
    std::string udid = softbusConnector_->GetDeviceUdidByUdidHash(devInfo.deviceId);
    DeviceProfileConnector::GetInstance().GetRemoteTokenIds(localUdid, udid, remoteTokenIds);
    std::unordered_set<int64_t> remoteServiceIds;
    for (const auto &item : remoteTokenIds) {
    }
    LOGI("remoteServiceIds size: %{public}zu", remoteServiceIds.size());

    CHECK_NULL_VOID(listener_);
    for (const auto &item : processInfoVec) {
        if (!item.pkgName.empty()) {
            LOGI("pkgName = %{public}s", item.pkgName.c_str());
            if (!remoteServiceIds.empty() && devState == DEVICE_STATE_ONLINE) {
                std::vector<int64_t> remoteServiceIdVec(remoteServiceIds.begin(), remoteServiceIds.end());
                listener_->OnDeviceStateChange(item, devState, devInfo, remoteServiceIdVec);
            } else {
                listener_->OnDeviceStateChange(item, devState, devInfo, isOnline);
            }
        }
    }
}
#else
void DmDeviceStateManager::ProcessDeviceStateChange(const DmDeviceState devState, const DmDeviceInfo &devInfo,
    std::vector<ProcessInfo> &processInfoVec, const bool isOnline)
{
    LOGI("begin, devState = %{public}d networkId: %{public}s.", devState,
        GetAnonyString(devInfo.networkId).c_str());
    CHECK_NULL_VOID(listener_);
    for (const auto &item : processInfoVec) {
        if (!item.pkgName.empty()) {
            listener_->OnDeviceStateChange(item, devState, devInfo, isOnline);
        }
    }
}
#endif

void DmDeviceStateManager::OnDbReady(const std::string &pkgName, const std::string &uuid)
{
    LOGI("function is called with pkgName: %{public}s and uuid = %{public}s",
         pkgName.c_str(), GetAnonyString(uuid).c_str());
    if (pkgName.empty() || uuid.empty()) {
        LOGE("On db ready pkgName is empty or uuid is empty");
        return;
    }
    DmDeviceInfo saveInfo;
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        auto iter = remoteDeviceInfos_.find(uuid);
        if (iter == remoteDeviceInfos_.end()) {
            LOGE("complete not find uuid: %{public}s", GetAnonyString(uuid).c_str());
            return;
        }
        saveInfo = iter->second;
    }
    if (listener_ != nullptr) {
        DmDeviceState state = DEVICE_INFO_READY;
        ProcessInfo processInfo;
        processInfo.pkgName = pkgName;
        processInfo.userId = MultipleUserConnector::GetFirstForegroundUserId();
        listener_->OnDeviceStateChange(processInfo, state, saveInfo, true);
    }
}

#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
void DmDeviceStateManager::RegisterOffLineTimer(const DmDeviceInfo &deviceInfo)
{
    std::string peerUdid;
    CHECK_NULL_VOID(softbusConnector_);
    int32_t ret = softbusConnector_->GetUdidByNetworkId(deviceInfo.networkId, peerUdid);
    if (ret != DM_OK) {
        LOGE("fail to get udid by networkId: %{public}s", GetAnonyString(deviceInfo.networkId).c_str());
        return;
    }
    int32_t localUserId = MultipleUserConnector::GetCurrentAccountUserID();
    LOGI("Register offline timer for udid: %{public}s, localUserId: %{public}d",
        GetAnonyString(peerUdid).c_str(), localUserId);
    std::unordered_set<int32_t> peerUserIds =
        DeviceProfileConnector::GetInstance().GetActiveAuthOncePeerUserId(peerUdid, localUserId);
    if (peerUserIds.empty()) {
        LOGE("fail to get peerUserId by peerUdid:%{public}s and localUserId:%{public}d",
            GetAnonyString(peerUdid).c_str(), localUserId);
        return;
    }
    std::lock_guard<ffrt::mutex> mutexLock(timerMapMutex_);
    if (timer_ == nullptr) {
        timer_ = std::make_shared<DmTimer>();
    }
    for (const auto &peerUserId : peerUserIds) {
        std::string key = peerUdid + "_" + std::to_string(peerUserId) + "_" +  std::to_string(localUserId);
        auto iter = stateTimerInfoMap_.find(key);
        if (iter != stateTimerInfoMap_.end()) {
            timer_->DeleteTimer(iter->second.timerName);
            stateTimerInfoMap_.erase(iter);
        }
        if (stateTimerInfoMap_.size() > AUTH_ONCE_STATE_TIMER_MAX) {
            LOGW("stateTimerInfoMap_ size more than limit, peerUdid:%{public}s, peerUserId:%{public}d,"
                " localUserId:%{public}d", GetAnonyString(peerUdid).c_str(), peerUserId, localUserId);
            return;
        }
        std::string sha256UdidHash = Crypto::Sha256(peerUdid);
        std::string timerName = std::string(STATE_TIMER_PREFIX) + sha256UdidHash + "_" + std::to_string(peerUserId) +
            "_" +  std::to_string(localUserId);
        StateTimerInfo stateTimer = {
            .timerName = timerName,
            .peerUdid = peerUdid,
            .peerUserId = peerUserId,
            .localUserId = localUserId,
            .isStart = false,
        };
        stateTimerInfoMap_[key] = stateTimer;
    }
}

void DmDeviceStateManager::StartOffLineTimer(const std::string &peerUdid)
{
    std::unordered_set<AuthOnceAclInfo, AuthOnceAclInfoHash> authOnceAclInfos =
        DeviceProfileConnector::GetInstance().GetAuthOnceAclInfos(peerUdid);
    if (authOnceAclInfos.empty()) {
        LOGE("fail to get peerUserId and localUserId by peerUdid:%{public}s", GetAnonyString(peerUdid).c_str());
        return;
    }
    std::lock_guard<ffrt::mutex> mutexLock(timerMapMutex_);
    if (timer_ == nullptr) {
        timer_ = std::make_shared<DmTimer>();
    }
    for (const auto &item : authOnceAclInfos) {
        LOGI("Start offline timer for peerUdid:%{public}s, peerUserId:%{public}d, localUserId:%{public}d",
            GetAnonyString(peerUdid).c_str(), item.peerUserId, item.localUserId);
        std::string key = peerUdid + "_" + std::to_string(item.peerUserId) + "_" +  std::to_string(item.localUserId);
        auto iter = stateTimerInfoMap_.find(key);
        if (iter == stateTimerInfoMap_.end() || iter->second.isStart) {
            continue;
        }
        timer_->StartTimer(iter->second.timerName, OFFLINE_TIMEOUT, [this] (std::string name) {
            DmDeviceStateManager::DeleteTimeOutGroup(name);
        });
        iter->second.isStart = true;
    }
}

void DmDeviceStateManager::DeleteTimeOutGroup(const std::string &timerName)
{
    LOGI("start timerName:%{public}s", timerName.c_str());
    std::lock_guard<ffrt::mutex> mutexLock(timerMapMutex_);
    if (hiChainConnector_ == nullptr || softbusConnector_ == nullptr) {
        LOGW("hiChainConnector_ or softbusConnector_ is nullptr");
        return;
    }
    auto iter = stateTimerInfoMap_.begin();
    for (;iter != stateTimerInfoMap_.end(); iter++) {
        if (iter->second.timerName == timerName) {
            break;
        }
    }
    if (iter == stateTimerInfoMap_.end()) {
        LOGW("not found by timerName:%{public}s", timerName.c_str());
        return;
    }
    auto timerInfo = iter->second;
    bool isOnline = softbusConnector_->CheckIsOnline(iter->second.peerUdid);
    bool isActive = DeviceProfileConnector::GetInstance().AuthOnceAclIsActive(timerInfo.peerUdid, timerInfo.peerUserId,
        timerInfo.localUserId);
    if (isOnline && isActive) {
        LOGW("device is online and status is acive peerUdid:%{public}s, peerUserId:%{public}d, localUserId:%{public}d",
            GetAnonyString(timerInfo.peerUdid).c_str(), timerInfo.peerUserId, timerInfo.localUserId);
        iter->second.isStart = false;
        return;
    }
    LOGI("remove hichain group with peerUdid:%{public}s, peerUserId:%{public}d, localUserId:%{public}d",
        GetAnonyString(timerInfo.peerUdid).c_str(), timerInfo.peerUserId, timerInfo.localUserId);
    hiChainConnector_->DeleteTimeOutGroup(timerInfo.peerUdid, timerInfo.localUserId);
    DeleteGroupByDP(timerInfo.peerUdid, timerInfo.peerUserId, timerInfo.localUserId);
    DmOfflineParam offlineParam;
    uint32_t allAclCnt = DeviceProfileConnector::GetInstance().DeleteTimeOutAcl(timerInfo.peerUdid,
        timerInfo.peerUserId, timerInfo.localUserId, offlineParam);
    if (allAclCnt > 0 && allAclCnt == static_cast<uint32_t>(offlineParam.needDelAclInfos.size())) {
        DeleteCredential(offlineParam, timerInfo.peerUdid, timerInfo.localUserId);
    }
    DeleteSkCredAndAcl(offlineParam.needDelAclInfos);
    stateTimerInfoMap_.erase(iter);
}

void DmDeviceStateManager::DeleteCredential(const DmOfflineParam &offlineParam, const std::string &peerUdid,
    int32_t localUserId)
{
    if (offlineParam.skIdVec.empty()) {
        CHECK_NULL_VOID(hiChainAuthConnector_);
        hiChainAuthConnector_->DeleteCredential(peerUdid, localUserId, offlineParam.peerUserId);
    }
}

int32_t DmDeviceStateManager::DeleteSkCredAndAcl(const std::vector<DmAclIdParam> &acls)
{
    LOGI("start.");
    int32_t ret = DM_OK;
    if (acls.empty()) {
        return ret;
    }
    CHECK_NULL_RETURN(hiChainAuthConnector_, ERR_DM_POINT_NULL);
    for (auto item : acls) {
        ret = DeviceProfileConnector::GetInstance().DeleteSessionKey(item.userId, item.skId);
        if (ret != DM_OK) {
            LOGE("DeleteSessionKey err, userId:%{public}d, skId:%{public}d, ret:%{public}d", item.userId, item.skId,
                ret);
        }
        DeleteCredential(item);
        DeviceProfileConnector::GetInstance().DeleteAccessControlById(item.accessControlId);
    }
    return ret;
}

void DmDeviceStateManager::DeleteCredential(const DmAclIdParam &acl)
{
    LOGI("by acl start.");
    CHECK_NULL_VOID(hiChainAuthConnector_);
    JsonObject credJson;
    int32_t ret = hiChainAuthConnector_->QueryCredInfoByCredId(acl.userId, acl.credId, credJson);
    if (ret != DM_OK || !credJson.Contains(acl.credId)) {
        LOGE("err, ret:%{public}d", ret);
        return;
    }
    if (!credJson[acl.credId].Contains(FILED_AUTHORIZED_APP_LIST)) {
        ret = hiChainAuthConnector_->DeleteCredential(acl.userId, acl.credId);
        if (ret != DM_OK) {
            LOGE("DeletecredId err, ret:%{public}d", ret);
        }
        return;
    }
    std::vector<std::string> appList;
    credJson[acl.credId][FILED_AUTHORIZED_APP_LIST].Get(appList);
    for (auto tokenId : acl.tokenIds) {
        auto iter = std::find(appList.begin(), appList.end(), std::to_string(tokenId));
        if (iter != appList.end()) {
            appList.erase(iter);
        }
    }
    if (appList.empty()) {
        ret = hiChainAuthConnector_->DeleteCredential(acl.userId, acl.credId);
        if (ret != DM_OK) {
            LOGE("DeletecredId err, ret:%{public}d", ret);
        }
        return;
    }
    ret = hiChainAuthConnector_->UpdateCredential(acl.credId, acl.userId, appList);
    if (ret != DM_OK) {
        LOGE("UpdateCredential err, ret:%{public}d", ret);
    }
}
#endif

void DmDeviceStateManager::DeleteOffLineTimer(const std::string &peerUdid)
{
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
    int32_t localUserId = MultipleUserConnector::GetCurrentAccountUserID();
    if (timer_ == nullptr || peerUdid.empty()) {
        return;
    }
    std::unordered_set<int32_t> peerUserIds =
        DeviceProfileConnector::GetInstance().GetActiveAuthOncePeerUserId(peerUdid, localUserId);
    if (peerUserIds.empty()) {
        LOGE("fail to get peerUserId by peerUdid and localUserId");
        return;
    }
    std::lock_guard<ffrt::mutex> mutexLock(timerMapMutex_);
    for (const auto &peerUserId : peerUserIds) {
        std::string key = peerUdid + "_" + std::to_string(peerUserId) + "_" +  std::to_string(localUserId);
        auto iter = stateTimerInfoMap_.find(key);
        if (iter == stateTimerInfoMap_.end()) {
            continue;
        }
        timer_->DeleteTimer(iter->second.timerName);
        stateTimerInfoMap_.erase(iter);
    }
#else
    (void)peerUdid;
#endif
}

void DmDeviceStateManager::StartEventThread()
{
    LOGD("begin");
    eventTask_.threadRunning_ = true;
    eventTask_.queueThread_ = std::thread([this]() { this->ThreadLoop(); });
    LOGD("complete");
}

void DmDeviceStateManager::StopEventThread()
{
    LOGI("begin");
    eventTask_.threadRunning_ = false;
    eventTask_.queueCond_.notify_all();
    eventTask_.queueFullCond_.notify_all();
    if (eventTask_.queueThread_.joinable()) {
        eventTask_.queueThread_.join();
    }
    LOGI("complete");
}

int32_t DmDeviceStateManager::AddTask(const std::shared_ptr<NotifyEvent> &task)
{
    LOGI("begin, eventId: %{public}d", task->GetEventId());
    {
        std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
        while (eventTask_.queue_.size() >= DM_EVENT_QUEUE_CAPACITY) {
            eventTask_.queueFullCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
        }
        eventTask_.queue_.push(task);
    }
    eventTask_.queueCond_.notify_one();
    LOGI("complete");
    return DM_OK;
}

void DmDeviceStateManager::ThreadLoop()
{
    LOGI("begin");
    int32_t ret = pthread_setname_np(pthread_self(), THREAD_LOOP);
    if (ret != DM_OK) {
        LOGE("setname failed.");
    }
    while (eventTask_.threadRunning_) {
        std::shared_ptr<NotifyEvent> task = nullptr;
        {
            std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
            while (eventTask_.queue_.empty() && eventTask_.threadRunning_) {
                eventTask_.queueCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
            }
            if (!eventTask_.queue_.empty()) {
                task = eventTask_.queue_.front();
                eventTask_.queue_.pop();
                eventTask_.queueFullCond_.notify_one();
            }
        }
        if (task != nullptr) {
            RunTask(task);
        }
    }
    LOGI("end");
}

void DmDeviceStateManager::RunTask(const std::shared_ptr<NotifyEvent> &task)
{
    LOGI("begin, eventId: %{public}d", task->GetEventId());
    if (task->GetEventId() == DM_NOTIFY_EVENT_ONDEVICEREADY) {
        OnDbReady(std::string(DM_PKG_NAME), task->GetDeviceId());
    }
    LOGI("complete");
}

DmAuthForm DmDeviceStateManager::GetAuthForm(const std::string &networkId)
{
    LOGI("start");
    if (hiChainConnector_ == nullptr) {
        LOGE("hiChainConnector_ is nullptr");
        return DmAuthForm::INVALID_TYPE;
    }

    if (networkId.empty()) {
        LOGE("networkId is empty");
        return DmAuthForm::INVALID_TYPE;
    }

    std::string udid;
    if (SoftbusConnector::GetUdidByNetworkId(networkId.c_str(), udid) == DM_OK) {
        return hiChainConnector_->GetGroupType(udid);
    }

    return DmAuthForm::INVALID_TYPE;
}

void DmDeviceStateManager::SaveNotifyEventInfos(const int32_t eventId, const std::string &deviceId)
{
    LOGI("in, eventId: %{public}d", eventId);
    DmDeviceInfo saveInfo;
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        auto iter = remoteDeviceInfos_.find(deviceId);
        if (iter == remoteDeviceInfos_.end()) {
            LOGE("complete not find deviceId: %{public}s", GetAnonyString(deviceId).c_str());
            return;
        }
        saveInfo = iter->second;
    }
    std::lock_guard<std::mutex> mutexLock(notifyEventInfosMutex_);
    notifyEventInfos_[deviceId] = saveInfo;
}

void DmDeviceStateManager::GetNotifyEventInfos(std::vector<DmDeviceInfo> &deviceList)
{
    std::lock_guard<std::mutex> mutexLock(notifyEventInfosMutex_);
    for (const auto &item: notifyEventInfos_) {
        deviceList.push_back(item.second);
    }
}

int32_t DmDeviceStateManager::ProcNotifyEvent(const int32_t eventId, const std::string &deviceId)
{
    LOGI("in, eventId: %{public}d", eventId);
    return AddTask(std::make_shared<NotifyEvent>(eventId, deviceId));
}

void DmDeviceStateManager::ChangeDeviceInfo(const DmDeviceInfo &info)
{
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
    std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
    std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
    for (auto iter : remoteDeviceInfos_) {
        if (std::string(iter.second.deviceId) == std::string(info.deviceId)) {
            if (memcpy_s(iter.second.deviceName, sizeof(iter.second.deviceName), info.deviceName,
                         sizeof(info.deviceName)) != DM_OK) {
                    LOGE("remoteDeviceInfos copy deviceName failed");
                    return;
            }
            if (memcpy_s(iter.second.networkId, sizeof(iter.second.networkId), info.networkId,
                         sizeof(info.networkId)) != DM_OK) {
                    LOGE("remoteDeviceInfos copy networkId failed");
                    return;
            }
            iter.second.deviceTypeId = info.deviceTypeId;
            LOGI("Change remoteDeviceInfos complete");
            break;
        }
    }
    for (auto iter : stateDeviceInfos_) {
        if (std::string(iter.second.deviceId) == std::string(info.deviceId)) {
            if (memcpy_s(iter.second.deviceName, sizeof(iter.second.deviceName), info.deviceName,
                         sizeof(info.deviceName)) != DM_OK) {
                    LOGE("stateDeviceInfos copy deviceName failed");
                    return;
            }
            if (memcpy_s(iter.second.networkId, sizeof(iter.second.networkId), info.networkId,
                         sizeof(info.networkId)) != DM_OK) {
                    LOGE("stateDeviceInfos copy networkId failed");
                    return;
            }
            iter.second.deviceTypeId = info.deviceTypeId;
            LOGI("Change stateDeviceInfos complete");
            break;
        }
    }
}

std::string DmDeviceStateManager::GetUdidByNetWorkId(std::string networkId)
{
    LOGI("networkId %{public}s", GetAnonyString(networkId).c_str());
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        for (auto &iter : stateDeviceInfos_) {
            if (networkId == iter.second.networkId) {
                return iter.first;
            }
        }
    }
    LOGI("Not find udid by networkid in stateDeviceInfos.");
    return "";
}

#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
int32_t DmDeviceStateManager::DeleteGroupByDP(const std::string &peerUdid, int32_t peerUserId, int32_t localUserId)
{
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles =
        DeviceProfileConnector::GetInstance().GetAccessControlProfileByUserId(localUserId);
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    std::vector<std::string> delPkgNameVec;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid || item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        auto accesser = item.GetAccesser();
        auto accessee = item.GetAccessee();
        if (accesser.GetAccesserDeviceId() == peerUdid && accesser.GetAccesserUserId() == peerUserId &&
            accessee.GetAccesseeUserId() == localUserId && !accessee.GetAccesseeBundleName().empty()) {
            delPkgNameVec.push_back(accessee.GetAccesseeBundleName());
        }
        if (accessee.GetAccesseeDeviceId() == peerUdid && accessee.GetAccesseeUserId() == peerUserId &&
            accesser.GetAccesserUserId() == localUserId && !accesser.GetAccesserBundleName().empty()) {
            delPkgNameVec.push_back(accesser.GetAccesserBundleName());
        }
    }
    if (delPkgNameVec.size() == 0) {
        LOGI("delPkgNameVec is empty");
        return DM_OK;
    }
    if (hiChainConnector_ == nullptr) {
        LOGE("hiChainConnector_ is nullptr");
        return ERR_DM_POINT_NULL;
    }
    std::vector<GroupInfo> groupListExt;
    hiChainConnector_->GetRelatedGroupsExt(peerUdid, groupListExt);
    for (auto &iter : groupListExt) {
        for (auto &pkgName : delPkgNameVec) {
            if (iter.groupName.find(pkgName) != std::string::npos) {
                int32_t ret = hiChainConnector_->DeleteGroupExt(localUserId, iter.groupId);
                LOGI("delete groupId %{public}s ,result %{public}d.",
                    GetAnonyString(iter.groupId).c_str(), ret);
            }
        }
    }
    return DM_OK;
}
#endif

bool DmDeviceStateManager::CheckIsOnline(const std::string &udid)
{
    LOGI("start, udid: %{public}s", GetAnonyString(std::string(udid)).c_str());
    {
#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
        std::lock_guard<ffrt::mutex> mutexLock(remoteDeviceInfosMutex_);
#else
        std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
#endif
        if (stateDeviceInfos_.find(udid) != stateDeviceInfos_.end()) {
            return true;
        }
    }
    return false;
}

void DmDeviceStateManager::HandleDeviceScreenStatusChange(DmDeviceInfo &devInfo,
    std::vector<ProcessInfo> &processInfos)
{
    CHECK_NULL_VOID(listener_);
    LOGI("pkgName size: %{public}zu", processInfos.size());
    for (const auto &item : processInfos) {
        listener_->OnDeviceScreenStateChange(item, devInfo);
    }
}

#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
void DmDeviceStateManager::StartDelTimerByDP(const std::string &peerUdid, int32_t peerUserId, int32_t localUserId)
{
    LOGI("peerUdid:%{public}s, peerUserId:%{public}d, localUserId:%{public}d",
        GetAnonyString(peerUdid).c_str(), peerUserId, localUserId);
    std::lock_guard<ffrt::mutex> mutexLock(timerMapMutex_);
    std::string key = peerUdid + "_" + std::to_string(peerUserId) + "_" +  std::to_string(localUserId);
    auto iter = stateTimerInfoMap_.find(key);
    if (iter != stateTimerInfoMap_.end() && iter->second.isStart) {
        return;
    }
    std::string sha256UdidHash = Crypto::Sha256(peerUdid);
    std::string timerName = std::string(STATE_TIMER_PREFIX) + sha256UdidHash + "_" + std::to_string(peerUserId) +
        "_" +  std::to_string(localUserId);
    if (iter == stateTimerInfoMap_.end()) {
        if (stateTimerInfoMap_.size() > AUTH_ONCE_STATE_TIMER_MAX) {
            LOGW("stateTimerInfoMap_ size more than limit");
            return;
        }
        StateTimerInfo stateTimer = {
            .timerName = timerName,
            .peerUdid = peerUdid,
            .peerUserId = peerUserId,
            .localUserId = localUserId,
            .isStart = true,
        };
        stateTimerInfoMap_[key] = stateTimer;
    } else {
        iter->second.isStart = true;
    }
    if (timer_ == nullptr) {
        timer_ = std::make_shared<DmTimer>();
    }
    timer_->StartTimer(timerName, OFFLINE_TIMEOUT, [this] (std::string name) {
        DmDeviceStateManager::DeleteTimeOutGroup(name);
    });
}
#endif
} // namespace DistributedHardware
} // namespace OHOS