/*
 * Copyright (c) 2023-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 <cstdio>

#include "deviceprofile_connector.h"
#include "crypto_mgr.h"
#include "dm_anonymous.h"
#include "dm_constants.h"
#include "dm_crypto.h"
#include "dm_device_info.h"
#include "dm_log.h"
#include "multiple_user_connector.h"
#include "distributed_device_profile_client.h"
#include "system_ability_definition.h"
#include "ipc_skeleton.h"
#include "dm_jsonstr_handle.h"
#include "app_manager.h"

using namespace OHOS::DistributedDeviceProfile;

const uint32_t INVALIED_TYPE = 0;
const uint32_t APP_PEER_TO_PEER_TYPE = 1;
const uint32_t APP_ACROSS_ACCOUNT_TYPE = 2;
const uint32_t SERVICE_PEER_TO_PEER_TYPE = 3;
const uint32_t SERVICE_ACROSS_ACCOUNT_TYPE = 4;
const uint32_t SHARE_TYPE = 5;
const uint32_t DEVICE_PEER_TO_PEER_TYPE = 6;
const uint32_t DEVICE_ACROSS_ACCOUNT_TYPE = 7;
const uint32_t IDENTICAL_ACCOUNT_TYPE = 8;
const uint32_t DM_INVALIED_TYPE = 2048;
const uint32_t SERVICE = 2;
const uint32_t APP = 3;
const uint32_t USER = 1;
const int64_t DM_DEFAULT_SERVICE_ID = 0;
constexpr uint32_t MAX_SESSION_KEY_LENGTH = 512;

const char* TAG_PEER_BUNDLE_NAME = "peerBundleName";
const char* TAG_PEER_TOKENID = "peerTokenId";
const char* TAG_ACL = "accessControlTable";
const char* TAG_DMVERSION = "dmVersion";
const char* TAG_ACL_HASH_KEY_VERSION = "aclVersion";
const char* TAG_ACL_HASH_KEY_ACLHASHLIST = "aclHashList";

namespace OHOS {
namespace DistributedHardware {
namespace {
const int32_t DM_SUPPORT_ACL_AGING_VERSION_NUM = 1;
const std::string DM_VERSION_STR_5_1_0 = DM_VERSION_5_1_0;
const std::vector<std::string> DM_SUPPORT_ACL_AGING_VERSIONS = {DM_VERSION_STR_5_1_0};
constexpr uint32_t AUTH_EXT_WHITE_LIST_NUM = 1;
constexpr const static char* g_extWhiteList[AUTH_EXT_WHITE_LIST_NUM] = {
    "CastEngineService",
};
enum DmDevBindType : int32_t {
    DEVICE_PEER_TO_PEER_BIND_TYPE = 3,
    DEVICE_ACROSS_ACCOUNT_BIND_TYPE = 4,
    IDENTICAL_ACCOUNT_BIND_TYPE = 5
};
constexpr int32_t INVALID_PROFILE_STATUS = -1;
}
IMPLEMENT_SINGLE_INSTANCE(DeviceProfileConnector);
void PrintProfile(const AccessControlProfile &profile)
{
    uint32_t bindType = profile.GetBindType();
    uint32_t bindLevel = profile.GetBindLevel();

    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();
    std::string acerAccountId = profile.GetAccesser().GetAccesserAccountId();
    std::string acerPkgName = profile.GetAccesser().GetAccesserBundleName();
    std::string acerCredId = profile.GetAccesser().GetAccesserCredentialIdStr();
    int32_t acerSkId = profile.GetAccesser().GetAccesserSessionKeyId();
    int64_t acerTokenId = profile.GetAccesser().GetAccesserTokenId();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    std::string aceeAccountId = profile.GetAccessee().GetAccesseeAccountId();
    std::string aceePkgName = profile.GetAccessee().GetAccesseeBundleName();
    std::string aceeCredId = profile.GetAccessee().GetAccesseeCredentialIdStr();
    int32_t aceeSkId = profile.GetAccessee().GetAccesseeSessionKeyId();
    int64_t aceeTokenId = profile.GetAccessee().GetAccesseeTokenId();

    LOGI("bindType %{public}d, bindLevel %{public}d, status %{public}d, acerDeviceId %{public}s, acerUserId %{public}d,"
        "acerAccountId %{public}s, acerPkgName %{public}s, acerCredId %{public}s,"
        "acerSkId %{public}d, aceeDeviceId %{public}s, aceeUserId %{public}d, aceeAccountId %{public}s,"
        "aceePkgName %{public}s, aceeCredId %{public}s, aceeSkId %{public}d,"
        "acerTokenId %{public}s, aceeTokenId %{public}s.",
        bindType, bindLevel, profile.GetStatus(), GetAnonyString(acerDeviceId).c_str(), acerUserId,
        GetAnonyString(acerAccountId).c_str(), acerPkgName.c_str(), GetAnonyString(acerCredId).c_str(), acerSkId,
        GetAnonyString(aceeDeviceId).c_str(), aceeUserId, GetAnonyString(aceeAccountId).c_str(),
        aceePkgName.c_str(), GetAnonyString(aceeCredId).c_str(), aceeSkId,
        GetAnonyInt64(acerTokenId).c_str(), GetAnonyInt64(aceeTokenId).c_str());
}

std::string GetLocalDeviceId()
{
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    return std::string(localDeviceId);
}

DM_EXPORT int32_t DeviceProfileConnector::GetVersionByExtra(std::string &extraInfo, std::string &dmVersion)
{
    JsonObject extraInfoJson(extraInfo);
    if (extraInfoJson.IsDiscarded()) {
        LOGE("extraInfoJson error");
        return ERR_DM_FAILED;
    }
    if (!extraInfoJson[TAG_DMVERSION].IsString()) {
        LOGE("PARAM_KEY_OS_VERSION error");
        return ERR_DM_FAILED;
    }
    dmVersion = extraInfoJson[TAG_DMVERSION].Get<std::string>();
    return DM_OK;
}

DM_EXPORT void DeviceProfileConnector::GetAllVerionAclMap(DistributedDeviceProfile::AccessControlProfile &acl,
    std::map<std::string, std::vector<std::string>> &aclMap, std::string dmVersion)
{
    std::vector<std::string> needGenVersions = {};
    // if not set version, send all support version acl hash
    if (dmVersion.empty()) {
        for (int32_t idx = 0; idx < DM_SUPPORT_ACL_AGING_VERSION_NUM; idx++) {
            needGenVersions.push_back(DM_SUPPORT_ACL_AGING_VERSIONS[idx]);
        }
    } else if (std::find(DM_SUPPORT_ACL_AGING_VERSIONS.begin(), DM_SUPPORT_ACL_AGING_VERSIONS.end(), dmVersion) !=
        DM_SUPPORT_ACL_AGING_VERSIONS.end()) {
        needGenVersions.push_back(dmVersion);
    } else {
        LOGE("dmVersion invalid, %{public}s", dmVersion.c_str());
        return;
    }

    for (auto const &version : needGenVersions) {
        GenerateAclHash(acl, aclMap, version);
    }
}

void DeviceProfileConnector::GenerateAclHash(DistributedDeviceProfile::AccessControlProfile &acl,
    std::map<std::string, std::vector<std::string>> &aclMap, const std::string &dmVersion)
{
    int32_t versionNum = 0;
    if (!GetVersionNumber(dmVersion, versionNum)) {
        LOGE("GetAllVerionAclMap GetVersionNumber error");
        return;
    }
    std::string aclStr;
    switch (versionNum) {
        case DM_VERSION_INT_5_1_0:
            aclStr = AccessToStr(acl);
            break;
        default:
            LOGE("versionNum is invaild, ver: %{public}d", versionNum);
            break;
    }
    if (aclStr.empty()) {
        return;
    }
    auto iter = aclMap.find(dmVersion);
    if (iter != aclMap.end()) {
        aclMap[dmVersion].push_back(Crypto::Sha256(aclStr));
    } else {
        std::vector<std::string> aclStrVec;
        aclStrVec.push_back(Crypto::Sha256(aclStr));
        aclMap[dmVersion] = aclStrVec;
    }
}

DM_EXPORT int32_t DeviceProfileConnector::GetAclListHashStr(const DevUserInfo &localDevUserInfo,
    const DevUserInfo &remoteDevUserInfo, std::string &aclListHash, std::string dmVersion)
{
    std::map<std::string, std::vector<std::string>> aclMap;
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles =
        DeviceProfileConnector::GetInstance().GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if (item.GetAccesser().GetAccesserDeviceId() == localDevUserInfo.deviceId &&
            item.GetAccesser().GetAccesserUserId() == localDevUserInfo.userId &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteDevUserInfo.deviceId &&
            item.GetAccessee().GetAccesseeUserId() == remoteDevUserInfo.userId) {
            GetAllVerionAclMap(item, aclMap, dmVersion);
            continue;
        }
        if (item.GetAccesser().GetAccesserDeviceId() == remoteDevUserInfo.deviceId &&
            item.GetAccesser().GetAccesserUserId() == remoteDevUserInfo.userId &&
            item.GetAccessee().GetAccesseeDeviceId() == localDevUserInfo.deviceId &&
            item.GetAccessee().GetAccesseeUserId() == localDevUserInfo.userId) {
            GetAllVerionAclMap(item, aclMap, dmVersion);
            continue;
        }
    }
    if (aclMap.empty()) {
        LOGI("acl list is empty");
    }
    std::vector<AclHashItem> aclStrVec;
    for (auto &item : aclMap) {
        aclStrVec.push_back({item.first, item.second});
    }
    JsonObject allAclObj(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
    AclHashVecToJson(allAclObj, aclStrVec);
    aclListHash = allAclObj.Dump();
    return DM_OK;
}

DM_EXPORT void DeviceProfileConnector::AclHashItemToJson(JsonItemObject &itemObject, const AclHashItem &value)
{
    itemObject[TAG_ACL_HASH_KEY_VERSION] = value.version;
    JsonObject hashList(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
    for (const auto &val : value.aclHashList) {
        hashList.PushBack(val);
    }
    itemObject[TAG_ACL_HASH_KEY_ACLHASHLIST] = hashList.Dump();
}

DM_EXPORT void DeviceProfileConnector::AclHashVecToJson(JsonItemObject &itemObject,
    const std::vector<AclHashItem> &values)
{
    for (const auto &val : values) {
        JsonObject object;
        AclHashItemToJson(object, val);
        itemObject.PushBack(object.Dump());
    }
}

DM_EXPORT void DeviceProfileConnector::AclHashItemFromJson(const JsonItemObject &itemObject, AclHashItem &value)
{
    if (itemObject.IsDiscarded() || !IsString(itemObject, TAG_ACL_HASH_KEY_VERSION) ||
        !IsString(itemObject, TAG_ACL_HASH_KEY_ACLHASHLIST)) {
        LOGE("Invalid JSON structure for ACL hash item");
        return;
    }
    value.version = itemObject[TAG_ACL_HASH_KEY_VERSION].Get<std::string>();
    std::string hashListStr = itemObject[TAG_ACL_HASH_KEY_ACLHASHLIST].Get<std::string>();
    JsonObject hashList;
    hashList.Parse(hashListStr);
    for (auto const &item : hashList.Items()) {
        if (item.IsDiscarded() || !item.IsString()) {
            LOGE("ACL hash list contains invalid element");
            continue;
        }
        value.aclHashList.push_back(item.Get<std::string>());
    }
}

DM_EXPORT void DeviceProfileConnector::AclHashVecFromJson(const JsonItemObject &itemObject,
    std::vector<AclHashItem> &values)
{
    for (auto const &item : itemObject.Items()) {
        JsonObject object;
        AclHashItem aclItem;
        if (item.IsDiscarded() || !item.IsString()) {
            LOGE("ItemObject contains invalid element");
            continue;
        }
        object.Parse(item.Get<std::string>());
        AclHashItemFromJson(object, aclItem);
        values.push_back(aclItem);
    }
}

DM_EXPORT bool DeviceProfileConnector::ChecksumAcl(DistributedDeviceProfile::AccessControlProfile &acl,
    std::vector<std::string> &acLStrList)
{
    std::string aclStr = AccessToStr(acl);
    auto aclIter = find(acLStrList.begin(), acLStrList.end(), Crypto::Sha256(aclStr));
    return (aclIter != acLStrList.end());
}

DM_EXPORT std::string DeviceProfileConnector::AccessToStr(DistributedDeviceProfile::AccessControlProfile acl)
{
    std::string aclStr = "";
    DistributedDeviceProfile::Accesser accesser = acl.GetAccesser();
    aclStr += accesser.GetAccesserDeviceId();
    aclStr += std::to_string(accesser.GetAccesserUserId());
    aclStr += accesser.GetAccesserAccountId();
    aclStr += std::to_string(accesser.GetAccesserTokenId());
    aclStr += accesser.GetAccesserBundleName();
    aclStr += accesser.GetAccesserHapSignature();
    aclStr += std::to_string(accesser.GetAccesserBindLevel());
    aclStr += accesser.GetAccesserCredentialIdStr();
    aclStr += std::to_string(accesser.GetAccesserStatus());
    aclStr += std::to_string(accesser.GetAccesserSKTimeStamp());

    DistributedDeviceProfile::Accessee accessee = acl.GetAccessee();
    aclStr += accessee.GetAccesseeDeviceId();
    aclStr += std::to_string(accessee.GetAccesseeUserId());
    aclStr += accessee.GetAccesseeAccountId();
    aclStr += std::to_string(accessee.GetAccesseeTokenId());
    aclStr += accessee.GetAccesseeBundleName();
    aclStr += accessee.GetAccesseeHapSignature();
    aclStr += std::to_string(accessee.GetAccesseeBindLevel());
    aclStr += accessee.GetAccesseeCredentialIdStr();
    aclStr += std::to_string(accessee.GetAccesseeStatus());
    aclStr += std::to_string(accessee.GetAccesseeSKTimeStamp());
    return aclStr;
}

DM_EXPORT std::vector<DistributedDeviceProfile::AccessControlProfile> DeviceProfileConnector::GetAclList(
    const std::string localUdid, int32_t localUserId, const std::string remoteUdid, int32_t remoteUserId)
{
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles =
        DeviceProfileConnector::GetInstance().GetAllAclIncludeLnnAcl();
    std::vector<DistributedDeviceProfile::AccessControlProfile> aclList;
    for (auto &item : profiles) {
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == localUserId &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
            item.GetAccessee().GetAccesseeUserId() == remoteUserId) {
            aclList.push_back(item);
            continue;
        }
        if (item.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
            item.GetAccesser().GetAccesserUserId() == remoteUserId &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeUserId() == localUserId) {
            aclList.push_back(item);
            continue;
        }
    }
    if (aclList.empty()) {
        LOGI("acl is empty");
    }
    return aclList;
}

DM_EXPORT std::string DeviceProfileConnector::IsAuthNewVersion(int32_t bindLevel, std::string localUdid,
    std::string remoteUdid, int32_t tokenId, int32_t userId)
{
    LOGI("localUdid %{public}s, remoteUdid %{public}s, bindLevel %{public}d.",
        GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), bindLevel);
    if (static_cast<uint32_t>(bindLevel) > APP || static_cast<uint32_t>(bindLevel) < USER) {
        LOGE("Invalied bindlevel bindLevel=%{public}u.", bindLevel);
        return "";
    }
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localUdid, userId);
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return "";
    }
    switch (bindLevel) {
        case APP:
        case SERVICE:
            return GetAppServiceAuthVersionInfo(localUdid, remoteUdid, tokenId, userId, profiles);
        case USER:
            return GetDeviceAuthVersionInfo(localUdid, remoteUdid, profiles);
        default:
            break;
    }
    return "";
}

std::string DeviceProfileConnector::GetAppServiceAuthVersionInfo(std::string localUdid, std::string remoteUdid,
    int32_t tokenId, int32_t userId, std::vector<DistributedDeviceProfile::AccessControlProfile> profiles)
{
    for (auto &item : profiles) {
        if (item.GetBindType() == DM_IDENTICAL_ACCOUNT ||
            (item.GetBindLevel() != APP && item.GetBindLevel() != SERVICE)) {
            continue;
        }
        int32_t acerUserId = item.GetAccesser().GetAccesserUserId();
        int32_t aceeUserId = item.GetAccessee().GetAccesseeUserId();
        std::string acerDeviceId = item.GetAccesser().GetAccesserDeviceId();
        std::string aceeDeviceId = item.GetAccessee().GetAccesseeDeviceId();
        int32_t acerTokenId = static_cast<int32_t>(item.GetAccesser().GetAccesserTokenId());
        int32_t aceeTokenId = static_cast<int32_t>(item.GetAccessee().GetAccesseeTokenId());
        if (acerUserId == userId && acerTokenId == tokenId &&
            acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
            return item.GetAccesser().GetAccesserExtraData();
        }
        if (aceeUserId == userId && aceeTokenId == tokenId &&
            aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
            return item.GetAccessee().GetAccesseeExtraData();
        }
    }
    return "";
}

std::string DeviceProfileConnector::GetDeviceAuthVersionInfo(std::string localUdid, std::string remoteUdid,
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles)
{
    for (auto &item : profiles) {
        if (item.GetBindType() == DM_IDENTICAL_ACCOUNT || item.GetBindLevel() != USER || IsLnnAcl(item)) {
            continue;
        }
        std::string acerDeviceId = item.GetAccesser().GetAccesserDeviceId();
        std::string aceeDeviceId = item.GetAccessee().GetAccesseeDeviceId();
        if (acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
            return item.GetAccesser().GetAccesserExtraData();
        }
        if (aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
            return item.GetAccessee().GetAccesseeExtraData();
        }
    }
    return "";
}

std::string DeviceProfileConnector::GetAclVersionInfo(const std::string localUdid, const std::string remoteUdid,
    const DistributedDeviceProfile::AccessControlProfile &acl)
{
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    if (acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
        return acl.GetAccesser().GetAccesserExtraData();
    }
    if (aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
        return acl.GetAccessee().GetAccesseeExtraData();
    }
    return "";
}

DM_EXPORT DmOfflineParam DeviceProfileConnector::FilterNeedDeleteACL(const std::string &localDeviceId,
    uint32_t localTokenId, const std::string &remoteDeviceId, const std::string &extra)
{
    LOGI("localDeviceId %{public}s, remoteDeviceId %{public}s",
        GetAnonyString(localDeviceId).c_str(), GetAnonyString(remoteDeviceId).c_str());
    DmOfflineParam offlineParam = {};
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localDeviceId, userId,
        remoteDeviceId);
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }

    FilterNeedDeleteACLInfos(profiles, localDeviceId, localTokenId, remoteDeviceId, extra, offlineParam);
    return offlineParam;
}

void DeviceProfileConnector::CheckLastLnnAcl(const std::string &localDeviceId, int32_t localUserId,
    const std::string &remoteDeviceId, DmOfflineParam &offlineParam,
    std::vector<DistributedDeviceProfile::AccessControlProfile> &profiles)
{
    LOGI("profiles size: %{public}zu", profiles.size());
    if (profiles.size() == 1 && IsLnnAcl(profiles[0])) {
        if (profiles[0].GetAccesser().GetAccesserDeviceId() == localDeviceId) {
            CacheAcerAclId(profiles[0], offlineParam.needDelAclInfos);
        }
        if (profiles[0].GetAccessee().GetAccesseeDeviceId() == localDeviceId) {
            CacheAceeAclId(profiles[0], offlineParam.needDelAclInfos);
        }
        offlineParam.hasLnnAcl = true;
    }
}

void DeviceProfileConnector::DeleteCacheAcl(std::vector<int64_t> delAclIdVec,
    std::vector<DistributedDeviceProfile::AccessControlProfile> &profiles)
{
    for (auto delAclId : delAclIdVec) {
        for (auto item = profiles.begin(); item != profiles.end();) {
            if (delAclId == item->GetAccessControlId()) {
                item = profiles.erase(item);
            } else {
                item++;
            }
        }
    }
}

bool DeviceProfileConnector::FindTargetAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const uint32_t localTokenId,
    const std::string &remoteUdid, const uint32_t peerTokenId,
    DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    int64_t acerTokenId = acl.GetAccesser().GetAccesserTokenId();
    int64_t aceeTokenId = acl.GetAccessee().GetAccesseeTokenId();
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    // Process target match acl which need delete
    if ((acerTokenId == static_cast<int64_t>(localTokenId)) &&
        (acerDeviceId == localUdid) && (aceeDeviceId == remoteUdid) &&
        (peerTokenId == 0 || (peerTokenId != 0 && aceeTokenId == static_cast<int64_t>(peerTokenId)))) {
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
        processInfo.userId = acl.GetAccesser().GetAccesserUserId();
        processInfo.tokenId = acl.GetAccesser().GetAccesserTokenId();
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
            processInfo.tokenId = 0;
        }
        offlineParam.processVec.push_back(processInfo);
        CacheAcerAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Src del acl aclId: %{public}" PRId64 ", localUdid: %{public}s, remoteUdid: %{public}s"
             ", bindType: %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
             GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
             acl.GetBindLevel());
        isMatch = true;
    }

    if ((aceeTokenId == static_cast<int64_t>(localTokenId)) &&
        (aceeDeviceId == localUdid) && (acerDeviceId == remoteUdid) &&
        (peerTokenId == 0 || (peerTokenId != 0 && acerTokenId == static_cast<int64_t>(peerTokenId)))) {
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
        processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
        processInfo.tokenId = acl.GetAccessee().GetAccesseeTokenId();
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
            processInfo.tokenId = 0;
        }
        offlineParam.processVec.push_back(processInfo);
        CacheAceeAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Sink del acl aclId: %{public}" PRId64 ", localUdid: %{public}s, remoteUdid: %{public}s"
             ", bindType: %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
             GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
             acl.GetBindLevel());
        isMatch = true;
    }
    return isMatch;
}

bool DeviceProfileConnector::FindLnnAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const std::string &remoteUdid, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    if (IsLnnAcl(acl) && acl.GetTrustDeviceId() == remoteUdid) {
        if (acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
            LOGI("Src lnn acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(),
                 GetAnonyString(remoteUdid).c_str(), acl.GetBindType(), acl.GetBindLevel());
            CacheAcerAclId(acl, offlineParam.allLnnAclInfos);
        }

        if (aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
            LOGI("Sink lnn acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
                 acl.GetBindLevel());
            CacheAceeAclId(acl, offlineParam.allLnnAclInfos);
        }
        isMatch = true;
    }
    return isMatch;
}

bool DeviceProfileConnector::FindUserAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const std::string &remoteUdid, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    // process User Or SameAccount acl
    if (acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT) {
        if (acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
            LOGI("Src User acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
                 acl.GetBindLevel());
            CacheAcerAclId(acl, offlineParam.allUserAclInfos);
        }

        if (aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
            LOGI("Sink User acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
                 acl.GetBindLevel());
            CacheAceeAclId(acl, offlineParam.allUserAclInfos);
        }
        isMatch = true;
    }
    return isMatch;
}

bool DeviceProfileConnector::FindLeftAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const std::string &remoteUdid, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    // process left service/app acl
    if (acl.GetBindLevel() == SERVICE || acl.GetBindLevel() == APP) {
        if (acerDeviceId == localUdid && aceeDeviceId == remoteUdid) {
            LOGI("Src Left acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
                 acl.GetBindLevel());
            CacheAcerAclId(acl, offlineParam.allLeftAppOrSvrAclInfos);
        }

        if (aceeDeviceId == localUdid && acerDeviceId == remoteUdid) {
            LOGI("Sink Left acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
                 ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
                 GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
                 acl.GetBindLevel());
            CacheAceeAclId(acl, offlineParam.allLeftAppOrSvrAclInfos);
        }
        isMatch = true;
    }
    return isMatch;
}

void DeviceProfileConnector::FilterNeedDeleteACLInfos(
    std::vector<DistributedDeviceProfile::AccessControlProfile> &profiles,
    const std::string &localUdid, const uint32_t localTokenId,
    const std::string &remoteUdid, const std::string &extra, DmOfflineParam &offlineParam)
{
    uint64_t peerTokenId = 0;
    std::string peerBundleName = "";
    JsonStrHandle::GetInstance().GetPeerAppInfoParseExtra(extra, peerTokenId, peerBundleName);
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }

        // First, find need delete acl
        if (FindTargetAcl(item, localUdid, localTokenId, remoteUdid, peerTokenId, offlineParam)) {
            continue;
        }

        // Second, find the LNN acl
        if (FindLnnAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Third, find the user or sameaccount acl, dertermine if report offline
        if (FindUserAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Fourth, find the left service/app acl, determine if del lnn acl
        if (FindLeftAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }
    }
}

//LCOV_EXCL_START
DM_EXPORT std::vector<AccessControlProfile> DeviceProfileConnector::GetAccessControlProfile()
{
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    return GetAccessControlProfileByUserId(userId);
}

std::vector<AccessControlProfile> DeviceProfileConnector::GetAccessControlProfileByUserId(int32_t userId)
{
    std::vector<AccessControlProfile> profiles;
    std::map<std::string, std::string> queryParams;
    queryParams[USERID] = std::to_string(userId);
    if (DistributedDeviceProfileClient::GetInstance().GetAccessControlProfile(queryParams, profiles) != DM_OK) {
        LOGE("DP GetAccessControlProfileByUserId failed.");
    }
    return profiles;
}

DM_EXPORT std::vector<AccessControlProfile> DeviceProfileConnector::GetAclProfileByDeviceIdAndUserId(
    const std::string &deviceId, int32_t userId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(userId);
    std::vector<AccessControlProfile> aclProfileVec;
    for (auto &item : profiles) {
        if ((item.GetAccesser().GetAccesserDeviceId() == deviceId &&
             item.GetAccesser().GetAccesserUserId() == userId) ||
            (item.GetAccessee().GetAccesseeDeviceId() == deviceId &&
             item.GetAccessee().GetAccesseeUserId() == userId)) {
            aclProfileVec.push_back(item);
        }
    }
    return aclProfileVec;
}
//LCOV_EXCL_STOP

DM_EXPORT std::vector<AccessControlProfile> DeviceProfileConnector::GetAclProfileByDeviceIdAndUserId(
    const std::string &deviceId, int32_t userId, const std::string &remoteDeviceId)
{
    std::vector<AccessControlProfile> aclProfileVec;
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if ((item.GetAccesser().GetAccesserDeviceId() == deviceId &&
             item.GetAccesser().GetAccesserUserId() == userId &&
             item.GetAccessee().GetAccesseeDeviceId() == remoteDeviceId) ||
            (item.GetAccessee().GetAccesseeDeviceId() == deviceId &&
             item.GetAccessee().GetAccesseeUserId() == userId &&
             item.GetAccesser().GetAccesserDeviceId() == remoteDeviceId)) {
            aclProfileVec.push_back(item);
        }
    }
    return aclProfileVec;
}

DM_EXPORT std::unordered_map<std::string, DmAuthForm> DeviceProfileConnector::GetAppTrustDeviceList(
    const std::string &pkgName, const std::string &deviceId)
{
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    LOGI("localDeviceId: %{public}s, userId: %{public}d", GetAnonyString(deviceId).c_str(), userId);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::vector<AccessControlProfile> profilesFilter = {};
    for (auto &item : profiles) {
        if (!IsLnnAcl(item) && ((item.GetAccesser().GetAccesserUserId() == userId &&
             item.GetAccesser().GetAccesserDeviceId() == deviceId) ||
            (item.GetAccessee().GetAccesseeUserId() == userId &&
             item.GetAccessee().GetAccesseeDeviceId() == deviceId))) {
            profilesFilter.push_back(item);
        }
    }
    return GetAuthFormMap(pkgName, deviceId, profilesFilter, userId);
}

std::unordered_map<std::string, DmAuthForm> DeviceProfileConnector::GetAuthFormMap(const std::string &pkgName,
    const std::string &deviceId, const std::vector<DistributedDeviceProfile::AccessControlProfile> &profilesFilter,
    const int32_t &userId)
{
    std::unordered_map<std::string, DmAuthForm> deviceIdMap;
    for (auto &item : profilesFilter) {
        std::string trustDeviceId = item.GetTrustDeviceId();
        LOGI("trustDeviceId: %{public}s, status: %{public}d, acerUserId: %{public}d, aceeUserId: %{public}d",
            GetAnonyString(trustDeviceId).c_str(), item.GetStatus(), item.GetAccesser().GetAccesserUserId(),
            item.GetAccessee().GetAccesseeUserId());
        if (trustDeviceId == deviceId || item.GetStatus() != ACTIVE) {
            continue;
        }
        DmDiscoveryInfo discoveryInfo = {pkgName, deviceId};
        int32_t bindType = HandleDmAuthForm(item, discoveryInfo);
        LOGI("The udid %{public}s in ACL authForm is %{public}d.", GetAnonyString(trustDeviceId).c_str(), bindType);
        if (bindType == DmAuthForm::INVALID_TYPE) {
            continue;
        }
        if (deviceIdMap.find(trustDeviceId) == deviceIdMap.end()) {
            if (CheckSinkShareType(item, userId, deviceId, trustDeviceId, bindType)) {
                LOGI("CheckSinkShareType true.");
                continue;
            }
            deviceIdMap[trustDeviceId] = static_cast<DmAuthForm>(bindType);
            continue;
        }
        DmAuthForm authForm = deviceIdMap.at(trustDeviceId);
        if (bindType == authForm) {
            continue;
        }
        uint32_t highestBindType = CheckBindType(trustDeviceId, deviceId);
        if (highestBindType == IDENTICAL_ACCOUNT_TYPE) {
            deviceIdMap[trustDeviceId] = DmAuthForm::IDENTICAL_ACCOUNT;
            continue;
        } else if (highestBindType == SHARE_TYPE) {
            if (CheckSinkShareType(item, userId, deviceId, trustDeviceId, DmAuthForm::SHARE)) {
                continue;
            }
            deviceIdMap[trustDeviceId] = DmAuthForm::SHARE;
            continue;
        } else if (highestBindType == DEVICE_PEER_TO_PEER_TYPE || highestBindType == APP_PEER_TO_PEER_TYPE ||
            highestBindType == SERVICE_PEER_TO_PEER_TYPE) {
            deviceIdMap[trustDeviceId] = DmAuthForm::PEER_TO_PEER;
            continue;
        } else if (highestBindType == APP_ACROSS_ACCOUNT_TYPE ||
            highestBindType == DEVICE_ACROSS_ACCOUNT_TYPE || highestBindType == SERVICE_ACROSS_ACCOUNT_TYPE) {
            deviceIdMap[trustDeviceId] = DmAuthForm::ACROSS_ACCOUNT;
            continue;
        } else {
            LOGE("highestBindType match failed.");
            continue;
        }
    }
    return deviceIdMap;
}

bool DeviceProfileConnector::CheckSinkShareType(const DistributedDeviceProfile::AccessControlProfile &profile,
    const int32_t &userId, const std::string &deviceId, const std::string &trustDeviceId, const int32_t &bindType)
{
    if (profile.GetAccessee().GetAccesseeUserId() == userId &&
        profile.GetAccessee().GetAccesseeDeviceId() == deviceId &&
        profile.GetAccesser().GetAccesserDeviceId() == trustDeviceId &&
        bindType == DmAuthForm::SHARE) {
        return true;
    }
    return false;
}

int32_t DeviceProfileConnector::GetDeviceAclParam(DmDiscoveryInfo discoveryInfo, bool &isOnline, int32_t &authForm)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(discoveryInfo.userId);
    std::vector<int32_t> bindTypes;
    for (auto &item : profiles) {
        char deviceIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
        if (Crypto::GetUdidHash(item.GetTrustDeviceId(), reinterpret_cast<uint8_t *>(deviceIdHash)) != DM_OK) {
            LOGE("get deviceIdHash by deviceId: %{public}s failed.", GetAnonyString(deviceIdHash).c_str());
            continue;
        }
        if (IsLnnAcl(item) || static_cast<std::string>(deviceIdHash) != discoveryInfo.remoteDeviceIdHash ||
            (discoveryInfo.localDeviceId == item.GetAccesser().GetAccesserDeviceId() &&
            discoveryInfo.userId != item.GetAccesser().GetAccesserUserId()) ||
            (discoveryInfo.localDeviceId == item.GetAccessee().GetAccesseeDeviceId() &&
            discoveryInfo.userId != item.GetAccessee().GetAccesseeUserId())) {
            continue;
        }
        int32_t bindType = HandleDmAuthForm(item, discoveryInfo);
        if (bindType == DmAuthForm::INVALID_TYPE) {
            continue;
        }
        bindTypes.push_back(bindType);
    }
    if (std::count(bindTypes.begin(), bindTypes.end(), DmAuthForm::IDENTICAL_ACCOUNT) > 0) {
        isOnline = true;
        authForm = DmAuthForm::IDENTICAL_ACCOUNT;
        LOGI("The found device is identical account device bind type.");
        return DM_OK;
    }
    if (std::count(bindTypes.begin(), bindTypes.end(), DmAuthForm::PEER_TO_PEER) > 0) {
        isOnline = true;
        authForm = DmAuthForm::PEER_TO_PEER;
        LOGI("The found device is peer-to-peer device bind-level.");
        return DM_OK;
    }
    if (std::count(bindTypes.begin(), bindTypes.end(), DmAuthForm::ACROSS_ACCOUNT) > 0) {
        isOnline = true;
        authForm = DmAuthForm::ACROSS_ACCOUNT;
        LOGI("The found device is across-account device bind-level.");
        return DM_OK;
    }
    authForm = DmAuthForm::INVALID_TYPE;
    return DM_OK;
}

bool DeviceProfileConnector::CheckAuthFormProxyTokenId(const std::string pkgName, const std::string &extraStr)
{
    std::vector<int64_t> proxyTokenIdVec = JsonStrHandle::GetInstance().GetProxyTokenIdByExtra(extraStr);
    int64_t callingTokenId = static_cast<int64_t>(IPCSkeleton::GetCallingTokenID());
    for (auto &proxyTokenId : proxyTokenIdVec) {
        std::string proxyBundleName;
        if (AppManager::GetInstance().GetBundleNameByTokenId(proxyTokenId, proxyBundleName) != DM_OK) {
            continue;
        }
        if (callingTokenId == proxyTokenId && pkgName == proxyBundleName) {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckAuthFormForAccesser(DmAuthForm form, const std::string &pkgName,
    const DistributedDeviceProfile::AccessControlProfile &profile, bool isSystemSA, uint32_t callingTokenId)
{
    const auto &accesser = profile.GetAccesser();
    if (isSystemSA) {
        if (pkgName == accesser.GetAccesserBundleName() ||
            CheckAuthFormProxyTokenId(pkgName, accesser.GetAccesserExtraData())) {
            return true;
        }
    } else {
        if (pkgName == accesser.GetAccesserBundleName() &&
            static_cast<uint64_t>(accesser.GetAccesserTokenId()) == callingTokenId) {
            LOGI("Non-systemSA matched: pkgName and tokenId as accesser.");
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckAuthFormForAccessee(DmAuthForm form, const std::string &pkgName,
    const DistributedDeviceProfile::AccessControlProfile &profile, bool isSystemSA, uint32_t callingTokenId)
{
    const auto &accessee = profile.GetAccessee();
    if (isSystemSA) {
        if (pkgName == accessee.GetAccesseeBundleName() ||
            CheckAuthFormProxyTokenId(pkgName, accessee.GetAccesseeExtraData())) {
            return true;
        }
    } else {
        if (pkgName == accessee.GetAccesseeBundleName() &&
            static_cast<uint64_t>(accessee.GetAccesseeTokenId()) == callingTokenId) {
            LOGI("Non-systemSA matched: pkgName and tokenId as accessee.");
            return true;
        }
    }
    return false;
}

int32_t DeviceProfileConnector::CheckAuthForm(DmAuthForm form, AccessControlProfile profiles,
    DmDiscoveryInfo discoveryInfo)
{
    if (IsLnnAcl(profiles)) {
        return DmAuthForm::INVALID_TYPE;
    }
    if (profiles.GetBindLevel() == USER || ((profiles.GetBindLevel() == APP ||
        profiles.GetBindLevel() == SERVICE) && discoveryInfo.pkgname == "")) {
        return form;
    }
    if (profiles.GetBindLevel() != APP && profiles.GetBindLevel() != SERVICE) {
        return DmAuthForm::INVALID_TYPE;
    }
    bool isSystemSA = AppManager::GetInstance().IsSystemSA();
    uint32_t callingTokenId = 0;
    if (!isSystemSA) {
        callingTokenId = IPCSkeleton::GetCallingTokenID();
        if (callingTokenId == 0) {
            LOGE("GetCallingTokenID error.");
            return DmAuthForm::INVALID_TYPE;
        }
    }
    if (discoveryInfo.localDeviceId == profiles.GetAccesser().GetAccesserDeviceId()) {
        if (CheckAuthFormForAccesser(form, discoveryInfo.pkgname, profiles, isSystemSA, callingTokenId)) {
            return form;
        }
    }
    if (discoveryInfo.localDeviceId == profiles.GetAccessee().GetAccesseeDeviceId()) {
        if (CheckAuthFormForAccessee(form, discoveryInfo.pkgname, profiles, isSystemSA, callingTokenId)) {
            return form;
        }
    }
    return DmAuthForm::INVALID_TYPE;
}

int32_t DeviceProfileConnector::HandleDmAuthForm(AccessControlProfile profiles, DmDiscoveryInfo discoveryInfo)
{
    if (profiles.GetBindType() == DM_IDENTICAL_ACCOUNT) {
        return DmAuthForm::IDENTICAL_ACCOUNT;
    }
    if (profiles.GetBindType() == DM_POINT_TO_POINT) {
        return CheckAuthForm(DmAuthForm::PEER_TO_PEER, profiles, discoveryInfo);
    }
    if (profiles.GetBindType() == DM_ACROSS_ACCOUNT) {
        return CheckAuthForm(DmAuthForm::PEER_TO_PEER, profiles, discoveryInfo);
    }
    if (profiles.GetBindType() == DM_SHARE) {
        return CheckAuthForm(DmAuthForm::SHARE, profiles, discoveryInfo);
    }
    return DmAuthForm::INVALID_TYPE;
}

DM_EXPORT uint32_t DeviceProfileConnector::CheckBindType(std::string peerUdid,
    std::string localUdid)
{
    std::vector<AccessControlProfile> filterProfiles = GetAclProfileByUserId(localUdid,
        MultipleUserConnector::GetFirstForegroundUserId(), peerUdid);
    LOGI("filterProfiles size is %{public}zu", filterProfiles.size());
    uint32_t highestPriority = INVALIED_TYPE;
    for (auto &item : filterProfiles) {
        if (IsLnnAcl(item) || peerUdid != item.GetTrustDeviceId()) {
            continue;
        }
        uint32_t priority = static_cast<uint32_t>(GetAuthForm(item, peerUdid, localUdid));
        if (priority > highestPriority) {
            highestPriority = priority;
        }
    }
    return highestPriority;
}

int32_t DeviceProfileConnector::GetAuthForm(DistributedDeviceProfile::AccessControlProfile profiles,
    const std::string &trustDev, const std::string &reqDev)
{
    LOGI("BindType %{public}d, bindLevel %{public}d", profiles.GetBindType(), profiles.GetBindLevel());
    uint32_t priority = INVALIED_TYPE;
    uint32_t bindType = profiles.GetBindType();

    switch (bindType) {
        case DM_IDENTICAL_ACCOUNT:
            priority = IDENTICAL_ACCOUNT_TYPE;
            break;
        case DM_SHARE:
            priority = SHARE_TYPE;
            break;
        case DM_POINT_TO_POINT:
            if (profiles.GetBindLevel() == USER) {
                priority = DEVICE_PEER_TO_PEER_TYPE;
            }
            if (profiles.GetBindLevel() == SERVICE) {
                priority = SERVICE_PEER_TO_PEER_TYPE;
            }
            if (profiles.GetBindLevel() == APP) {
                priority = APP_PEER_TO_PEER_TYPE;
            }
            break;
        case DM_ACROSS_ACCOUNT:
            if (profiles.GetBindLevel() == USER) {
                priority = DEVICE_ACROSS_ACCOUNT_TYPE;
            }
            if (profiles.GetBindLevel() == SERVICE) {
                priority = SERVICE_ACROSS_ACCOUNT_TYPE;
            }
            if (profiles.GetBindLevel() == APP) {
                priority = APP_ACROSS_ACCOUNT_TYPE;
            }
            break;
        default:
            LOGE("unknown bind type %{public}d.", bindType);
            break;
    }
    return priority;
}

DM_EXPORT std::vector<int32_t> DeviceProfileConnector::GetBindTypeByPkgName(
    std::string pkgName, std::string requestDeviceId, std::string trustUdid)
{
    LOGI("Start requestDeviceId %{public}s, trustUdid %{public}s.", GetAnonyString(requestDeviceId).c_str(),
        GetAnonyString(trustUdid).c_str());
    std::vector<int32_t> bindTypeVec;
    if (requestDeviceId.empty() || trustUdid.empty() || requestDeviceId == trustUdid) {
        LOGE("Input udid param invalied.");
        return bindTypeVec;
    }
    std::vector<AccessControlProfile> profiles =
        GetAccessControlProfileByUserId(MultipleUserConnector::GetFirstForegroundUserId());
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    for (auto &item : profiles) {
        if (IsLnnAcl(item) || trustUdid != item.GetTrustDeviceId() || item.GetStatus() != ACTIVE) {
            continue;
        }
        GetParamBindTypeVec(item, requestDeviceId, bindTypeVec, trustUdid);
    }
    return bindTypeVec;
}

DM_EXPORT uint64_t DeviceProfileConnector::GetTokenIdByNameAndDeviceId(std::string extra, std::string requestDeviceId)
{
    uint64_t peerTokenId = 0;
    std::string pkgName = "";
    JsonStrHandle::GetInstance().GetPeerAppInfoParseExtra(extra, peerTokenId, pkgName);
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    for (auto &item : profiles) {
        if (item.GetAccesser().GetAccesserBundleName() == pkgName &&
            item.GetAccesser().GetAccesserDeviceId() == requestDeviceId) {
            peerTokenId = static_cast<uint64_t>(item.GetAccesser().GetAccesserTokenId());
            break;
        }
        if (item.GetAccessee().GetAccesseeBundleName() == pkgName &&
            item.GetAccessee().GetAccesseeDeviceId() == requestDeviceId) {
            peerTokenId = static_cast<uint64_t>(item.GetAccessee().GetAccesseeTokenId());
            break;
        }
    }
    return peerTokenId;
}

void DeviceProfileConnector::GetParamBindTypeVec(AccessControlProfile profile, std::string requestDeviceId,
    std::vector<int32_t> &bindTypeVec, std::string trustUdid)
{
    if (!(profile.GetAccesser().GetAccesserDeviceId() == trustUdid &&
        profile.GetAccessee().GetAccesseeDeviceId() == requestDeviceId) &&
        !(profile.GetAccessee().GetAccesseeDeviceId() == trustUdid &&
        profile.GetAccesser().GetAccesserDeviceId() == requestDeviceId)) {
        LOGE("input udid param invalied.");
        return;
    }
    uint32_t bindType = profile.GetBindType();
    switch (bindType) {
        case DM_IDENTICAL_ACCOUNT:
            bindTypeVec.push_back(DmDevBindType::IDENTICAL_ACCOUNT_BIND_TYPE);
            break;
        case DM_POINT_TO_POINT:
            if (profile.GetBindLevel() == USER) {
                bindTypeVec.push_back(DmDevBindType::DEVICE_PEER_TO_PEER_BIND_TYPE);
            }
            if (profile.GetBindLevel() == APP) {
                bindTypeVec.push_back(APP_PEER_TO_PEER_TYPE);
            }
            break;
        case DM_ACROSS_ACCOUNT:
            if (profile.GetBindLevel() == USER) {
                bindTypeVec.push_back(DmDevBindType::DEVICE_ACROSS_ACCOUNT_BIND_TYPE);
            }
            if (profile.GetBindLevel() == APP) {
                bindTypeVec.push_back(APP_ACROSS_ACCOUNT_TYPE);
            }
            break;
        default:
            LOGE("unknown bind type %{public}d.", bindType);
            break;
    }
}

std::vector<int32_t> DeviceProfileConnector::CompareBindType(std::vector<AccessControlProfile> profiles,
    std::string pkgName, std::vector<int32_t> &sinkBindType, std::string localDeviceId, std::string targetDeviceId)
{
    std::vector<int32_t> bindTypeIndex;
    for (uint32_t index = 0; index < profiles.size(); index++) {
        if (IsLnnAcl(profiles[index]) || profiles[index].GetTrustDeviceId() != targetDeviceId ||
            profiles[index].GetStatus() != ACTIVE) {
            continue;
        }
        DmDiscoveryInfo paramInfo = {
            .pkgname = pkgName,
            .localDeviceId = localDeviceId,
        };
        ProcessBindType(profiles[index], localDeviceId, sinkBindType, bindTypeIndex, index, targetDeviceId);
    }
    return bindTypeIndex;
}

void DeviceProfileConnector::ProcessBindType(AccessControlProfile profiles, std::string localDeviceId,
    std::vector<int32_t> &sinkBindType, std::vector<int32_t> &bindTypeIndex,
    uint32_t index, std::string targetDeviceId)
{
    if (profiles.GetBindType() == DM_IDENTICAL_ACCOUNT) {
        sinkBindType.push_back(DmDevBindType::IDENTICAL_ACCOUNT_BIND_TYPE);
        bindTypeIndex.push_back(index);
    }
    if (profiles.GetBindType() == DM_POINT_TO_POINT) {
        if (profiles.GetBindLevel() == USER) {
            sinkBindType.push_back(DmDevBindType::DEVICE_PEER_TO_PEER_BIND_TYPE);
            bindTypeIndex.push_back(index);
        }
        if (profiles.GetBindLevel() == APP) {
            if (profiles.GetAccesser().GetAccesserDeviceId() == targetDeviceId &&
                profiles.GetAccessee().GetAccesseeDeviceId() == localDeviceId) {
                sinkBindType.push_back(APP_PEER_TO_PEER_TYPE);
                bindTypeIndex.push_back(index);
            }
            if (profiles.GetAccessee().GetAccesseeDeviceId() == targetDeviceId &&
                profiles.GetAccesser().GetAccesserDeviceId() == localDeviceId) {
                sinkBindType.push_back(APP_PEER_TO_PEER_TYPE);
                bindTypeIndex.push_back(index);
            }
        }
    }
    if (profiles.GetBindType() == DM_ACROSS_ACCOUNT) {
        if (profiles.GetBindLevel() == USER) {
            sinkBindType.push_back(DmDevBindType::DEVICE_ACROSS_ACCOUNT_BIND_TYPE);
            bindTypeIndex.push_back(index);
        }
        if (profiles.GetBindLevel() == APP) {
            if (profiles.GetAccesser().GetAccesserDeviceId() == targetDeviceId &&
                profiles.GetAccessee().GetAccesseeDeviceId() == localDeviceId) {
                sinkBindType.push_back(APP_ACROSS_ACCOUNT_TYPE);
                bindTypeIndex.push_back(index);
            }
            if (profiles.GetAccessee().GetAccesseeDeviceId() == targetDeviceId &&
                profiles.GetAccesser().GetAccesserDeviceId() == localDeviceId) {
                sinkBindType.push_back(APP_ACROSS_ACCOUNT_TYPE);
                bindTypeIndex.push_back(index);
            }
        }
    }
}

DM_EXPORT std::vector<int32_t> DeviceProfileConnector::SyncAclByBindType(
    std::string pkgName, std::vector<int32_t> bindTypeVec, std::string localDeviceId, std::string targetDeviceId)
{
    std::vector<AccessControlProfile> profiles =
        GetAccessControlProfileByUserId(MultipleUserConnector::GetFirstForegroundUserId());
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    std::vector<int32_t> sinkBindType;
    std::vector<int32_t> bindType;
    std::vector<int32_t> bindTypeIndex =
        CompareBindType(profiles, pkgName, sinkBindType, localDeviceId, targetDeviceId);
    LOGI("sinkBindType size is %{public}zu", sinkBindType.size());
    for (uint32_t sinkIndex = 0; sinkIndex < sinkBindType.size(); sinkIndex++) {
        bool deleteAclFlag = true;
        for (uint32_t srcIndex = 0; srcIndex < bindTypeVec.size(); srcIndex++) {
            if (sinkBindType[sinkIndex] == bindTypeVec[srcIndex]) {
                deleteAclFlag = false;
                bindType.push_back(bindTypeVec[srcIndex]);
            }
        }
        if (deleteAclFlag) {
            int32_t deleteIndex = profiles[bindTypeIndex[sinkIndex]].GetAccessControlId();
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(deleteIndex);
            LOGI("deleteAcl index is %{public}d", deleteIndex);
        }
    }
    return bindType;
}

DM_EXPORT std::vector<OHOS::DistributedHardware::ProcessInfo> DeviceProfileConnector::GetProcessInfoFromAclByUserId(
    const std::string &localDeviceId, const std::string &targetDeviceId, int32_t userId)
{
    std::vector<AccessControlProfile> filterProfiles = GetAclProfileByUserId(localDeviceId,
        userId, targetDeviceId);
    LOGI("filterProfiles size is %{public}zu", filterProfiles.size());
    std::vector<OHOS::DistributedHardware::ProcessInfo> processInfoVec;
    for (auto &item : filterProfiles) {
        if (IsLnnAcl(item) || item.GetTrustDeviceId() != targetDeviceId) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        OHOS::DistributedHardware::ProcessInfo processInfo;
        std::string extraStr;
        if (accesserUdid == localDeviceId) {
            processInfo.pkgName = item.GetAccesser().GetAccesserBundleName();
            processInfo.userId = item.GetAccesser().GetAccesserUserId();
            processInfo.tokenId = static_cast<uint32_t>(item.GetAccesser().GetAccesserTokenId());
            processInfoVec.push_back(processInfo);
            extraStr = item.GetAccesser().GetAccesserExtraData();
        } else if (accesseeUdid == localDeviceId) {
            processInfo.pkgName = item.GetAccessee().GetAccesseeBundleName();
            processInfo.userId = item.GetAccessee().GetAccesseeUserId();
            processInfo.tokenId = static_cast<uint32_t>(item.GetAccessee().GetAccesseeTokenId());
            processInfoVec.push_back(processInfo);
            extraStr = item.GetAccessee().GetAccesseeExtraData();
        } else {
            continue;
        }
        std::vector<int64_t> proxyTokenIdVec = JsonStrHandle::GetInstance().GetProxyTokenIdByExtra(extraStr);
        for (auto &proxyTokenId : proxyTokenIdVec) {
            std::string proxyBundleName;
            if (AppManager::GetInstance().GetBundleNameByTokenId(proxyTokenId, proxyBundleName) != DM_OK) {
                continue;
            }
            processInfo.pkgName = proxyBundleName;
            processInfoVec.push_back(processInfo);
        }
    }
    return processInfoVec;
}

DM_EXPORT AccessControlProfile DeviceProfileConnector::GetAccessControlProfileByAccessControlId(
    int64_t accessControlId)
{
    AccessControlProfile profile;
    profile.SetAccessControlId(0);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if (item.GetAccessControlId() == accessControlId) {
            return item;
        }
    }
    return profile;
}

DM_EXPORT std::vector<std::pair<int64_t, int64_t>> DeviceProfileConnector::GetAgentToProxyVecFromAclByUserId(
    const std::string &localDeviceId, const std::string &targetDeviceId, int32_t userId)
{
    std::vector<AccessControlProfile> filterProfiles = GetAclProfileByUserId(localDeviceId,
        userId, targetDeviceId);
    LOGI("filterProfiles size is %{public}zu", filterProfiles.size());
    std::vector<std::pair<int64_t, int64_t>> agentToProxyVec;
    for (auto &item : filterProfiles) {
        if (IsLnnAcl(item) || item.GetTrustDeviceId() != targetDeviceId) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int64_t agentTokenId;
        std::string extraStr;
        if (accesserUdid == localDeviceId) {
            agentTokenId = item.GetAccesser().GetAccesserTokenId();
            extraStr = item.GetAccesser().GetAccesserExtraData();
        } else if (accesseeUdid == localDeviceId) {
            agentTokenId = item.GetAccessee().GetAccesseeTokenId();
            extraStr = item.GetAccessee().GetAccesseeExtraData();
        } else {
            continue;
        }
        std::vector<int64_t> proxyTokenIdVec = JsonStrHandle::GetInstance().GetProxyTokenIdByExtra(extraStr);
        for (auto &proxyTokenId : proxyTokenIdVec) {
            agentToProxyVec.push_back(std::pair<int64_t, int64_t>(agentTokenId, proxyTokenId));
        }
    }
    return agentToProxyVec;
}

int32_t DeviceProfileConnector::PutAccessControlList(DmAclInfo aclInfo, DmAccesser dmAccesser, DmAccessee dmAccessee)
{
    LOGI("Start.");
    Accesser accesser;
    accesser.SetAccesserDeviceId(dmAccesser.requestDeviceId);
    accesser.SetAccesserUserId(dmAccesser.requestUserId);
    accesser.SetAccesserAccountId(dmAccesser.requestAccountId);
    accesser.SetAccesserTokenId(dmAccesser.requestTokenId);
    accesser.SetAccesserBundleName(dmAccesser.requestBundleName);
    accesser.SetAccesserDeviceName(dmAccesser.requestDeviceName);
    Accessee accessee;
    accessee.SetAccesseeDeviceId(dmAccessee.trustDeviceId);
    accessee.SetAccesseeUserId(dmAccessee.trustUserId);
    accessee.SetAccesseeAccountId(dmAccessee.trustAccountId);
    accessee.SetAccesseeTokenId(dmAccessee.trustTokenId);
    accessee.SetAccesseeBundleName(dmAccessee.trustBundleName);
    accessee.SetAccesseeDeviceName(dmAccessee.trustDeviceName);
    AccessControlProfile profile;
    profile.SetBindType(aclInfo.bindType);
    profile.SetBindLevel(aclInfo.bindLevel);
    profile.SetStatus(ACTIVE);
    profile.SetTrustDeviceId(aclInfo.trustDeviceId);
    profile.SetDeviceIdType((int32_t)DeviceIdType::UDID);
    profile.SetDeviceIdHash(aclInfo.deviceIdHash);
    profile.SetAuthenticationType(aclInfo.authenticationType);
    profile.SetAccessee(accessee);
    profile.SetAccesser(accesser);
    int32_t ret = DistributedDeviceProfileClient::GetInstance().PutAccessControlProfile(profile);
    if (ret != DM_OK) {
        LOGE("PutAccessControlProfile failed.");
    }
    return ret;
}

DM_EXPORT bool DeviceProfileConnector::DeleteAclForAccountLogOut(
    const DMAclQuadInfo &info, const std::string &accountId, DmOfflineParam &offlineParam,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("localUdid %{public}s, localUserId %{public}d, peerUdid %{public}s, peerUserId %{public}d.",
        GetAnonyString(info.localUdid).c_str(), info.localUserId, GetAnonyString(info.peerUdid).c_str(),
        info.peerUserId);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    bool notifyOffline = false;
    for (const auto &item : profiles) {
        if (item.GetTrustDeviceId() != info.peerUdid) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        std::string accesserAccountId = item.GetAccesser().GetAccesserAccountId();
        std::string accesseeAccountId = item.GetAccessee().GetAccesseeAccountId();
        if (accesserUdid == info.localUdid && accesserUserId == info.localUserId &&
            accesseeUdid == info.peerUdid && accesseeUserId == info.peerUserId &&
            accesserAccountId == accountId) {
            ProcessLocalAccessRemote(item, info, accountId, offlineParam, serviceInfos, notifyOffline);
            continue;
        }
        if (accesserUdid == info.peerUdid && accesserUserId == info.peerUserId &&
            accesseeUdid == info.localUdid && accesseeUserId == info.localUserId &&
            accesseeAccountId == accountId) {
            ProcessRemoteAccessLocal(item, info, accountId, offlineParam, serviceInfos, notifyOffline);
            continue;
        }
    }
    return notifyOffline;
}

void DeviceProfileConnector::ProcessLocalAccessRemote(
    const AccessControlProfile &item, const DMAclQuadInfo &info, const std::string &accountId,
    DmOfflineParam &offlineParam, std::vector<DmUserRemovedServiceInfo> &serviceInfos, bool &notifyOffline)
{
    offlineParam.bindType = item.GetBindType();
    SetProcessInfoPkgName(item, offlineParam.processVec, true);
    notifyOffline = (item.GetStatus() == ACTIVE);
    CacheAcerAclId(item, offlineParam.needDelAclInfos);
    if (IsLnnAcl(item)) {
        return;
    }
    if (FillDmUserRemovedServiceInfoRemote(item, serviceInfos) != DM_OK) {
        return;
    }
}

void DeviceProfileConnector::ProcessRemoteAccessLocal(
    const AccessControlProfile &item, const DMAclQuadInfo &info, const std::string &accountId,
    DmOfflineParam &offlineParam, std::vector<DmUserRemovedServiceInfo> &serviceInfos, bool &notifyOffline)
{
    offlineParam.bindType = item.GetBindType();
    SetProcessInfoPkgName(item, offlineParam.processVec, false);
    notifyOffline = (item.GetStatus() == ACTIVE);
    CacheAceeAclId(item, offlineParam.needDelAclInfos);
    if (IsLnnAcl(item)) {
        return;
    }
    FillDmUserRemovedServiceInfoLocal(item, serviceInfos);
}

DM_EXPORT bool DeviceProfileConnector::DeleteAclByActhash(
    const DMAclQuadInfo &info, const std::string &accountIdHash, DmOfflineParam &offlineParam,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("localUdid %{public}s, localUserId %{public}d, peerUdid %{public}s, peerUserId %{public}d.",
        GetAnonyString(info.localUdid).c_str(), info.localUserId, GetAnonyString(info.peerUdid).c_str(),
        info.peerUserId);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    bool notifyOffline = false;
    for (const auto &item : profiles) {
        if (item.GetTrustDeviceId() != info.peerUdid) {
            continue;
        }
        DmCacheOfflineInputParam inputParam;
        inputParam.profile = item;
        inputParam.info = info;
        inputParam.accountIdHash = accountIdHash;
        CacheOfflineParam(inputParam, offlineParam, notifyOffline, serviceInfos);
    }
    return notifyOffline;
}

void DeviceProfileConnector::CacheOfflineParam(const DmCacheOfflineInputParam &inputParam,
    DmOfflineParam &offlineParam, bool &notifyOffline, std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("start.");
    DistributedDeviceProfile::AccessControlProfile profile = inputParam.profile;
    DMAclQuadInfo info = inputParam.info;
    std::string accountIdHash = inputParam.accountIdHash;
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t accesserUserId = profile.GetAccesser().GetAccesserUserId();
    int32_t accesseeUserId = profile.GetAccessee().GetAccesseeUserId();
    std::string accesserAccountId = profile.GetAccesser().GetAccesserAccountId();
    std::string accesseeAccountId = profile.GetAccessee().GetAccesseeAccountId();
    char accesserAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    if (Crypto::GetAccountIdHash(accesserAccountId, reinterpret_cast<uint8_t *>(accesserAccountIdHash)) != DM_OK) {
        LOGE("GetAccountHash failed.");
        return;
    }
    char accesseeAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    if (Crypto::GetAccountIdHash(accesseeAccountId, reinterpret_cast<uint8_t *>(accesseeAccountIdHash)) != DM_OK) {
        LOGE("GetAccountHash failed.");
        return;
    }
    if (accesserUdid == info.localUdid && accesserUserId == info.localUserId &&
        accesseeUdid == info.peerUdid && accesseeUserId == info.peerUserId &&
        std::string(accesseeAccountIdHash) == accountIdHash) {
        ProcessLocalToPeer(profile, info, accountIdHash, offlineParam, notifyOffline, serviceInfos);
        return;
    }
    if (accesserUdid == info.peerUdid && accesserUserId == info.peerUserId &&
        accesseeUdid == info.localUdid && accesseeUserId == info.localUserId &&
        std::string(accesserAccountIdHash) == accountIdHash) {
        ProcessPeerToLocal(profile, info, accountIdHash, offlineParam, notifyOffline, serviceInfos);
        return;
    }
}
void DeviceProfileConnector::ProcessLocalToPeer(
    const DistributedDeviceProfile::AccessControlProfile &profile, const DMAclQuadInfo &info,
    const std::string &accountIdHash, DmOfflineParam &offlineParam, bool &notifyOffline,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    offlineParam.bindType = profile.GetBindType();
    SetProcessInfoPkgName(profile, offlineParam.processVec, true);
    notifyOffline = (profile.GetStatus() == ACTIVE);
    CacheAcerAclId(profile, offlineParam.needDelAclInfos);
    if (IsLnnAcl(profile)) {
        return;
    }
    if (FillDmUserRemovedServiceInfoRemote(profile, serviceInfos) != DM_OK) {
        return;
    }
}

void DeviceProfileConnector::ProcessPeerToLocal(
    const DistributedDeviceProfile::AccessControlProfile &profile, const DMAclQuadInfo &info,
    const std::string &accountIdHash, DmOfflineParam &offlineParam, bool &notifyOffline,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    offlineParam.bindType = profile.GetBindType();
    SetProcessInfoPkgName(profile, offlineParam.processVec, false);
    notifyOffline = (profile.GetStatus() == ACTIVE);
    CacheAceeAclId(profile, offlineParam.needDelAclInfos);
    if (IsLnnAcl(profile)) {
        return;
    }
    FillDmUserRemovedServiceInfoLocal(profile, serviceInfos);
}

void DeviceProfileConnector::SaveInvalidSkIdAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    std::map<std::string, DmOfflineParam> &invalidAclMap, bool isLocalAccer, DmOfflineParam &dmParam)
{
    std::string acerUdid = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeUdid = acl.GetAccessee().GetAccesseeDeviceId();
    if (isLocalAccer) {
        if (invalidAclMap.find(aceeUdid) != invalidAclMap.end()) {
            CacheAcerAclId(acl, invalidAclMap[aceeUdid].needDelAclInfos);
            FindLeftAcl(acl, acerUdid, aceeUdid, invalidAclMap[aceeUdid]);
            FindUserAcl(acl, acerUdid, aceeUdid, invalidAclMap[aceeUdid]);
            FindLnnAcl(acl, acerUdid, aceeUdid, invalidAclMap[aceeUdid]);
        } else {
            CacheAcerAclId(acl, dmParam.needDelAclInfos);
            FindLeftAcl(acl, acerUdid, aceeUdid, dmParam);
            FindUserAcl(acl, acerUdid, aceeUdid, dmParam);
            FindLnnAcl(acl, acerUdid, aceeUdid, dmParam);
            invalidAclMap.insert(std::pair<std::string, DmOfflineParam>(aceeUdid, dmParam));
        }
    } else {
        if (invalidAclMap.find(acerUdid) != invalidAclMap.end()) {
            CacheAceeAclId(acl, invalidAclMap[acerUdid].needDelAclInfos);
            FindLeftAcl(acl, aceeUdid, acerUdid, invalidAclMap[acerUdid]);
            FindUserAcl(acl, aceeUdid, acerUdid, invalidAclMap[acerUdid]);
            FindLnnAcl(acl, aceeUdid, acerUdid, invalidAclMap[acerUdid]);
        } else {
            CacheAceeAclId(acl, dmParam.needDelAclInfos);
            FindLeftAcl(acl, aceeUdid, acerUdid, dmParam);
            FindUserAcl(acl, aceeUdid, acerUdid, dmParam);
            FindLnnAcl(acl, aceeUdid, acerUdid, dmParam);
            invalidAclMap.insert(std::pair<std::string, DmOfflineParam>(acerUdid, dmParam));
        }
    }
}

bool DeviceProfileConnector::SaveInvalidAclMap(const DistributedDeviceProfile::AccessControlProfile &acl,
    bool isLocalAccer, DmOfflineParam &dmParam, std::set<int32_t> &invalidSkIdSet,
    std::map<std::string, DmOfflineParam> &invalidAclMap)
{
    int32_t skId = -1;
    int32_t userId = -1;
    if (isLocalAccer) {
        skId = acl.GetAccesser().GetAccesserSessionKeyId();
        userId = acl.GetAccesser().GetAccesserUserId();
    } else {
        skId = acl.GetAccessee().GetAccesseeSessionKeyId();
        userId = acl.GetAccessee().GetAccesseeUserId();
    }

    if (invalidSkIdSet.find(skId) != invalidSkIdSet.end()) {
        PrintProfile(acl);
        SaveInvalidSkIdAcl(acl, invalidAclMap, isLocalAccer, dmParam);
        return true;
    }
    std::vector<unsigned char> sessionKey;
    int32_t ret = GetSessionKey(userId, skId, sessionKey);
    if (ret != DM_OK || sessionKey.empty()) {
        LOGE("GetSessionKey failed ret:%{public}d", ret);
        PrintProfile(acl);
        SaveInvalidSkIdAcl(acl, invalidAclMap, isLocalAccer, dmParam);
        invalidSkIdSet.insert(skId);
        return true;
    }
    return false;
}

DM_EXPORT void DeviceProfileConnector::GetInvalidSkIdAcl(std::map<std::string, DmOfflineParam> &invalidAclMap)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::set<int32_t> invalidSkIdSet;
    int32_t localUserId = MultipleUserConnector::TryGetCurrentAccountUserID();
    if (localUserId == -1) {
        LOGE("get current userId failed");
        return;
    }
    std::string localUdid = GetLocalDeviceId();
    for (auto &item : profiles) {
        if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
            continue;
        }
        DmOfflineParam dmParam;
        std::string acerUdid = item.GetAccesser().GetAccesserDeviceId();
        int32_t acerUserId = item.GetAccesser().GetAccesserUserId();
        if (acerUdid == localUdid && localUserId == acerUserId) {
            LOGI("is src");
            if (SaveInvalidAclMap(item, true, dmParam, invalidSkIdSet, invalidAclMap)) {
                continue;
            }
        }
        std::string aceeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t aceeUserId = item.GetAccessee().GetAccesseeUserId();
        if (aceeUdid == localUdid && localUserId == aceeUserId) {
            LOGI("is sink");
            if (SaveInvalidAclMap(item, false, dmParam, invalidSkIdSet, invalidAclMap)) {
                continue;
            }
        }
    }
}

DM_EXPORT void DeviceProfileConnector::DeleteAclForUserRemoved(const DmLocalUserRemovedInfo &userRemovedInfo,
    std::multimap<std::string, int32_t> &peerUserIdMap, DmOfflineParam &offlineParam,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (const auto &item : profiles) {
        if (find(userRemovedInfo.peerUdids.begin(), userRemovedInfo.peerUdids.end(),
            item.GetTrustDeviceId()) == userRemovedInfo.peerUdids.end()) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == userRemovedInfo.localUdid && accesserUserId == userRemovedInfo.preUserId) {
            if (!IsValueExist(peerUserIdMap, accesseeUdid, accesseeUserId)) {
                peerUserIdMap.insert(std::pair<std::string, int32_t>(accesseeUdid, accesseeUserId));
            }
            CacheAcerAclId(item, offlineParam.needDelAclInfos);
            if (IsLnnAcl(item)) {
                continue;
            }
            if (FillDmUserRemovedServiceInfoRemote(item, serviceInfos) != DM_OK) {
                continue;
            }
            continue;
        }
        if (accesseeUdid == userRemovedInfo.localUdid && accesseeUserId == userRemovedInfo.preUserId) {
            if (!IsValueExist(peerUserIdMap, accesserUdid, accesserUserId)) {
                peerUserIdMap.insert(std::pair<std::string, int32_t>(accesserUdid, accesserUserId));
            }
            CacheAceeAclId(item, offlineParam.needDelAclInfos);
            if (IsLnnAcl(item)) {
                continue;
            }
            FillDmUserRemovedServiceInfoLocal(item, serviceInfos);
            continue;
        }
    }
}

DM_EXPORT void DeviceProfileConnector::DeleteAclForRemoteUserRemoved(
    DmRemoteUserRemovedInfo &userRemovedInfo, DmOfflineParam &offlineParam,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("peerUdid %{public}s, peerUserId %{public}d.", GetAnonyString(userRemovedInfo.peerUdid).c_str(),
        userRemovedInfo.peerUserId);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (const auto &item : profiles) {
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == userRemovedInfo.peerUdid && accesserUserId == userRemovedInfo.peerUserId) {
            if (item.GetBindLevel() == USER) {
                userRemovedInfo.localUserIds.push_back(accesseeUserId);
            }
            CacheAceeAclId(item, offlineParam.needDelAclInfos);
            if (IsLnnAcl(item)) {
                continue;
            }
            FillDmUserRemovedServiceInfoLocal(item, serviceInfos);
            continue;
        }
        if (accesseeUdid == userRemovedInfo.peerUdid && accesseeUserId == userRemovedInfo.peerUserId) {
            if (item.GetBindLevel() == USER) {
                userRemovedInfo.localUserIds.push_back(accesserUserId);
            }
            CacheAcerAclId(item, offlineParam.needDelAclInfos);
            if (IsLnnAcl(item)) {
                continue;
            }
            if (FillDmUserRemovedServiceInfoRemote(item, serviceInfos) != DM_OK) {
                continue;
            }
        }
    }
}

DM_EXPORT void DeviceProfileConnector::DeleteAccessControlList(const std::string &udid)
{
    LOGI("Udid: %{public}s.", GetAnonyString(udid).c_str());
    if (udid.empty()) {
        LOGE("udid is empty.");
        return;
    }
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    LOGI("Size is %{public}zu", profiles.size());
    for (const auto &item : profiles) {
        if (item.GetTrustDeviceId() == udid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
        }
    }
}

DM_EXPORT DmOfflineParam DeviceProfileConnector::FilterNeedDeleteACL(const std::string &peerUdid)
{
    std::string localUdid = GetLocalDeviceId();
    LOGI("localUdid %{public}s, peerUdid %{public}s",
        GetAnonyString(localUdid).c_str(), GetAnonyString(peerUdid).c_str());
    DmOfflineParam offlineParam;
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localUdid, userId,
        peerUdid);
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }

    FilterNeedDeleteACLInfos(profiles, localUdid, peerUdid, offlineParam);
    return offlineParam;
}

bool DeviceProfileConnector::IsAuthNewVersion(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string localUdid, const std::string remoteUdid)
{
    std::string extraInfo = GetAclVersionInfo(localUdid, remoteUdid, acl);
    JsonObject extraInfoJson(extraInfo);
    if (extraInfoJson.IsDiscarded()) {
        LOGE("extraInfoJson error");
        return false;
    }
    if (!extraInfoJson[TAG_DMVERSION].IsString()) {
        LOGE("PARAM_KEY_OS_VERSION error");
        return false;
    }
    std::string dmVersion = extraInfoJson[TAG_DMVERSION].Get<std::string>();
    if (CompareVersion(dmVersion, std::string(DM_VERSION_5_1_0)) || dmVersion == std::string(DM_VERSION_5_1_0)) {
        return true;
    }
    return false;
}

void DeviceProfileConnector::FilterNeedDeleteACLInfos(
    std::vector<DistributedDeviceProfile::AccessControlProfile> &profiles,
    const std::string &localUdid, const std::string &peerUdid, DmOfflineParam &offlineParam)
{
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid) {
            continue;
        }
        bool isNewVersion = IsAuthNewVersion(item, localUdid, peerUdid);
        offlineParam.isNewVersion = isNewVersion;
        // find need delete acl
        if (isNewVersion && FindTargetAclIncludeLnn(item, localUdid, peerUdid, offlineParam)) {
            continue;
        }
        if (!isNewVersion && FindTargetAclIncludeLnnOld(item, localUdid, peerUdid, offlineParam)) {
            continue;
        }
    }
}

bool DeviceProfileConnector::FindTargetAclIncludeLnn(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const std::string &remoteUdid, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    if (acl.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
        acl.GetAccessee().GetAccesseeDeviceId() == localUdid) {
        if (!IsLnnAcl(acl) && (acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        if (!IsLnnAcl(acl)) {
            ProcessInfo processInfo;
            processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
            processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
            offlineParam.processVec.push_back(processInfo);
        }
        CacheAceeAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Src del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }

    if (acl.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
        acl.GetAccesser().GetAccesserDeviceId() == localUdid) {
        if (!IsLnnAcl(acl) && (acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        if (!IsLnnAcl(acl)) {
            ProcessInfo processInfo;
            processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
            processInfo.userId = acl.GetAccesser().GetAccesserUserId();
            offlineParam.processVec.push_back(processInfo);
        }
        CacheAcerAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Sink del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    return isMatch;
}

bool DeviceProfileConnector::FindTargetAclIncludeLnnOld(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const std::string &remoteUdid, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    if (acl.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
        acl.GetAccessee().GetAccesseeDeviceId() == localUdid) {
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
        processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
        offlineParam.processVec.push_back(processInfo);
        offlineParam.peerUserId = acl.GetAccesser().GetAccesserUserId();
        CacheAceeAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Src del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }

    if (acl.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
        acl.GetAccesser().GetAccesserDeviceId() == localUdid) {
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
        processInfo.userId = acl.GetAccesser().GetAccesserUserId();
        offlineParam.processVec.push_back(processInfo);
        offlineParam.peerUserId = acl.GetAccessee().GetAccesseeUserId();
        CacheAcerAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Sink del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    return isMatch;
}

DmOfflineParam DeviceProfileConnector::DeleteAccessControlList(const std::string &pkgName,
    const std::string &localDeviceId, const std::string &remoteDeviceId,
    int32_t bindLevel, const std::string &extra)
{
    LOGI("pkgName %{public}s, localDeviceId %{public}s, remoteDeviceId %{public}s, bindLevel %{public}d.",
        pkgName.c_str(), GetAnonyString(localDeviceId).c_str(), GetAnonyString(remoteDeviceId).c_str(), bindLevel);
    DmOfflineParam offlineParam;
    offlineParam.bindType = INVALIED_TYPE;
    if (static_cast<uint32_t>(bindLevel) > APP || static_cast<uint32_t>(bindLevel) < USER) {
        LOGE("Invalied bindlevel.");
        return offlineParam;
    }
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localDeviceId,
        MultipleUserConnector::GetFirstForegroundUserId());
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }
    switch (bindLevel) {
        case APP:
            if (extra == "") {
                DeleteAppBindLevel(offlineParam, pkgName, profiles, localDeviceId, remoteDeviceId);
            } else {
                DeleteAppBindLevel(offlineParam, pkgName, profiles, localDeviceId, remoteDeviceId, extra);
            }
            break;
        case SERVICE:
            DeleteServiceBindLevel(offlineParam, pkgName, profiles, localDeviceId, remoteDeviceId);
            break;
        case USER:
            DeleteDeviceBindLevel(offlineParam, profiles, localDeviceId, remoteDeviceId);
            break;
        default:
            break;
    }
    return offlineParam;
}

void DeviceProfileConnector::DeleteAppBindLevel(DmOfflineParam &offlineParam, const std::string &pkgName,
    const std::vector<AccessControlProfile> &profiles, const std::string &localUdid, const std::string &remoteUdid)
{
    int32_t bindNums = 0;
    int32_t deleteNums = 0;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid || item.GetBindType() == DM_IDENTICAL_ACCOUNT ||
            item.GetBindLevel() != APP) {
            continue;
        }
        bindNums++;
        if (item.GetAccesser().GetAccesserBundleName() == pkgName &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = APP;
            ProcessInfo processInfo;
            processInfo.pkgName = item.GetAccesser().GetAccesserBundleName();
            processInfo.userId = item.GetAccesser().GetAccesserUserId();
            offlineParam.processVec.push_back(processInfo);
            offlineParam.peerUserId = item.GetAccessee().GetAccesseeUserId();
            LOGI("Src delete acl pkgName %{public}s, bindType %{public}d, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
        if (item.GetAccessee().GetAccesseeBundleName() == pkgName &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = APP;
            ProcessInfo processInfo;
            processInfo.pkgName = item.GetAccessee().GetAccesseeBundleName();
            processInfo.userId = item.GetAccessee().GetAccesseeUserId();
            offlineParam.processVec.push_back(processInfo);
            offlineParam.peerUserId = item.GetAccesser().GetAccesserUserId();
            LOGI("Sink delete acl pkgName %{public}s, bindType %{public}u, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
    }
    offlineParam.leftAclNumber = bindNums - deleteNums;
}

void DeviceProfileConnector::DeleteAppBindLevel(DmOfflineParam &offlineParam, const std::string &pkgName,
    const std::vector<AccessControlProfile> &profiles, const std::string &localUdid,
    const std::string &remoteUdid, const std::string &extra)
{
    int32_t bindNums = 0;
    int32_t deleteNums = 0;
    uint64_t peerTokenId = 0;
    std::string peerBundleName;
    JsonStrHandle::GetInstance().GetPeerAppInfoParseExtra(extra, peerTokenId, peerBundleName);
    LOGI("peerBundleName %{public}s", peerBundleName.c_str());
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid || item.GetBindType() == DM_IDENTICAL_ACCOUNT ||
            item.GetBindLevel() != APP) {
            continue;
        }
        bindNums++;
        if (item.GetAccesser().GetAccesserBundleName() == pkgName &&
            item.GetAccessee().GetAccesseeBundleName() == peerBundleName &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = APP;
            ProcessInfo processInfo;
            processInfo.pkgName = item.GetAccesser().GetAccesserBundleName();
            processInfo.userId = item.GetAccesser().GetAccesserUserId();
            offlineParam.processVec.push_back(processInfo);
            offlineParam.peerUserId = item.GetAccessee().GetAccesseeUserId();
            LOGI("Src delete acl pkgName %{public}s, bindType %{public}d, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
        if (item.GetAccessee().GetAccesseeBundleName() == pkgName &&
            item.GetAccesser().GetAccesserBundleName() == peerBundleName &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = APP;
            ProcessInfo processInfo;
            processInfo.pkgName = item.GetAccessee().GetAccesseeBundleName();
            processInfo.userId = item.GetAccessee().GetAccesseeUserId();
            offlineParam.processVec.push_back(processInfo);
            offlineParam.peerUserId = item.GetAccesser().GetAccesserUserId();
            LOGI("Sink delete acl pkgName %{public}s, bindType %{public}u, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
    }
    offlineParam.leftAclNumber = bindNums - deleteNums;
}

void DeviceProfileConnector::DeleteDeviceBindLevel(DmOfflineParam &offlineParam,
    const std::vector<AccessControlProfile> &profiles, const std::string &localUdid, const std::string &remoteUdid)
{
    int32_t bindNums = 0;
    int32_t deleteNums = 0;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid || item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
            continue;
        }
        bindNums++;
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = USER;
            LOGI("Src delete acl bindType %{public}d, localUdid %{public}s, remoteUdid %{public}s", item.GetBindType(),
                GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str());
            continue;
        }
        if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = USER;
            LOGI("Sink delete acl bindType %{public}u, localUdid %{public}s, remoteUdid %{public}s", item.GetBindType(),
                GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str());
            continue;
        }
    }
    offlineParam.leftAclNumber = bindNums - deleteNums;
}

void DeviceProfileConnector::DeleteServiceBindLevel(DmOfflineParam &offlineParam, const std::string &pkgName,
    const std::vector<AccessControlProfile> &profiles, const std::string &localUdid, const std::string &remoteUdid)
{
    int32_t bindNums = 0;
    int32_t deleteNums = 0;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid || item.GetBindType() == DM_IDENTICAL_ACCOUNT ||
            item.GetBindLevel() != SERVICE) {
            continue;
        }
        bindNums++;
        if (item.GetAccesser().GetAccesserBundleName() == pkgName &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = SERVICE;
            LOGI("Src delete acl pkgName %{public}s, bindType %{public}d, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
        if (item.GetAccessee().GetAccesseeBundleName() == pkgName &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            deleteNums++;
            offlineParam.bindType = SERVICE;
            LOGI("Sink delete acl pkgName %{public}s, bindType %{public}u, localUdid %{public}s, remoteUdid %{public}s",
                pkgName.c_str(), item.GetBindType(), GetAnonyString(localUdid).c_str(),
                GetAnonyString(remoteUdid).c_str());
            continue;
        }
    }
    offlineParam.leftAclNumber = bindNums - deleteNums;
}

DM_EXPORT void DeviceProfileConnector::UpdateAclStatus(const DistributedDeviceProfile::AccessControlProfile &profile)
{
    DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
}

int32_t DeviceProfileConnector::UpdateAccessControlList(int32_t userId, std::string &oldAccountId,
    std::string &newAccountId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    for (auto &item : profiles) {
        if ((item.GetAccesser().GetAccesserUserId() == userId &&
            item.GetAccesser().GetAccesserAccountId() == oldAccountId) ||
            (item.GetAccessee().GetAccesseeUserId() == userId &&
            item.GetAccessee().GetAccesseeAccountId() == oldAccountId)) {
            item.SetStatus(INACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        }
        if ((item.GetAccesser().GetAccesserUserId() == userId &&
            item.GetAccesser().GetAccesserAccountId() == newAccountId) ||
            (item.GetAccessee().GetAccesseeUserId() == userId &&
            item.GetAccessee().GetAccesseeAccountId() == newAccountId)) {
            item.SetStatus(ACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        }
    }
    return DM_OK;
}

DM_EXPORT bool DeviceProfileConnector::CheckSrcDevIdInAclForDevBind(
    const std::string &pkgName, const std::string &deviceId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() == deviceId && item.GetStatus() == ACTIVE &&
            item.GetBindLevel() == USER && (item.GetAccessee().GetAccesseeBundleName() == pkgName ||
            item.GetAccesser().GetAccesserBundleName() == "") && item.GetAccessee().GetAccesseeUserId() == 0 &&
            item.GetAccessee().GetAccesseeAccountId() == "") {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkDevIdInAclForDevBind(const std::string &pkgName, const std::string &deviceId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() == deviceId && item.GetStatus() == ACTIVE &&
            item.GetBindLevel() == USER && (item.GetAccesser().GetAccesserBundleName() == pkgName ||
            item.GetAccesser().GetAccesserBundleName() == "") && item.GetAccesser().GetAccesserUserId() == 0 &&
            item.GetAccesser().GetAccesserAccountId() == "") {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckDevIdInAclForDevBind(const std::string &pkgName, const std::string &deviceId)
{
    return (CheckSinkDevIdInAclForDevBind(pkgName, deviceId) || CheckSrcDevIdInAclForDevBind(pkgName, deviceId));
}

bool DeviceProfileConnector::MatchAccesseeByBothUserIdAndPeerUdid(const std::string &peerUdid, int32_t peerUserId,
    int32_t localUserId, const AccessControlProfile &aclProfile)
{
    auto accesser = aclProfile.GetAccesser();
    auto accessee = aclProfile.GetAccessee();
    if (accessee.GetAccesseeDeviceId() == peerUdid && accessee.GetAccesseeUserId() == peerUserId &&
        accesser.GetAccesserUserId() == localUserId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::MatchAccesserByBothUserIdAndPeerUdid(const std::string &peerUdid, int32_t peerUserId,
    int32_t localUserId, const AccessControlProfile &aclProfile)
{
    auto accesser = aclProfile.GetAccesser();
    auto accessee = aclProfile.GetAccessee();
    if (accesser.GetAccesserDeviceId() == peerUdid && accesser.GetAccesserUserId() == peerUserId &&
        accessee.GetAccesseeUserId() == localUserId) {
        return true;
    }
    return false;
}

DM_EXPORT uint32_t DeviceProfileConnector::DeleteTimeOutAcl(const std::string &peerUdid, int32_t peerUserId,
    int32_t localUserId, DmOfflineParam &offlineParam)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    uint32_t allAclCnt = 0;
    uint32_t noLnnAclCnt = 0;
    DmAclIdParam lnnDmAclIdParam;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid ||
            !(item.GetBindType() == DM_POINT_TO_POINT || item.GetBindType() == DM_ACROSS_ACCOUNT)) {
            continue;
        }
        allAclCnt++;
        if (!(MatchAccesseeByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item) ||
            MatchAccesserByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item))) {
            continue;
        }
        if (CacheLnnAcl(item, peerUdid, peerUserId, localUserId, lnnDmAclIdParam)) {
            continue;
        }
        noLnnAclCnt++;
        if (item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        if (MatchAccesserByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item)) {
            CacheAceeAclId(item, offlineParam.needDelAclInfos);
        }
        if (MatchAccesseeByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item)) {
            CacheAcerAclId(item, offlineParam.needDelAclInfos);
        }
    }
    LOGI("allAclCnt:%{public}u, noLnnAclCnt:%{public}u, needDelAclInfos.size:%{public}zu, lnnAclId:%{public}" PRId64,
        allAclCnt, noLnnAclCnt, offlineParam.needDelAclInfos.size(), lnnDmAclIdParam.accessControlId);
    if (noLnnAclCnt > 0 && noLnnAclCnt == static_cast<uint32_t>(offlineParam.needDelAclInfos.size()) &&
        lnnDmAclIdParam.accessControlId > 0) {
        offlineParam.needDelAclInfos.push_back(lnnDmAclIdParam);
    }
    offlineParam.peerUserId = peerUserId;
    return allAclCnt;
}

bool DeviceProfileConnector::CacheLnnAcl(const AccessControlProfile &profile, const std::string &peerUdid,
    int32_t peerUserId, int32_t localUserId, DmAclIdParam &dmAclIdParam)
{
    if (IsLnnAcl(profile)) {
        auto accesser = profile.GetAccesser();
        auto accessee = profile.GetAccessee();
        if (accesser.GetAccesserDeviceId() != peerUdid && accesser.GetAccesserUserId() == localUserId &&
            accessee.GetAccesseeUserId() == peerUserId) {
            dmAclIdParam.udid = accesser.GetAccesserDeviceId();
            dmAclIdParam.userId = localUserId;
            dmAclIdParam.skId = accesser.GetAccesserSessionKeyId();
            dmAclIdParam.credId = accesser.GetAccesserCredentialIdStr();
            dmAclIdParam.tokenIds.insert(accessee.GetAccesseeTokenId());
            dmAclIdParam.tokenIds.insert(accesser.GetAccesserTokenId());
            dmAclIdParam.accessControlId = profile.GetAccessControlId();
        }
        if (accessee.GetAccesseeDeviceId() != peerUdid && accessee.GetAccesseeUserId() == localUserId &&
            accesser.GetAccesserUserId() == peerUserId) {
            dmAclIdParam.udid = accessee.GetAccesseeDeviceId();
            dmAclIdParam.userId = localUserId;
            dmAclIdParam.skId = accessee.GetAccesseeSessionKeyId();
            dmAclIdParam.credId = accessee.GetAccesseeCredentialIdStr();
            dmAclIdParam.tokenIds.insert(accessee.GetAccesseeTokenId());
            dmAclIdParam.tokenIds.insert(accesser.GetAccesserTokenId());
            dmAclIdParam.accessControlId = profile.GetAccessControlId();
        }
        return true;
    }
    return false;
}

DM_EXPORT int32_t DeviceProfileConnector::GetTrustNumber(const std::string &deviceId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    LOGI("AccessControlProfile size is %{public}zu", profiles.size());
    int32_t trustNumber = 0;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() == deviceId && item.GetStatus() == ACTIVE) {
            trustNumber++;
        }
    }
    return trustNumber;
}

DM_EXPORT int32_t DeviceProfileConnector::IsSameAccount(const std::string &udid)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() == udid && item.GetStatus() == ACTIVE) {
            if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
                LOGI("The udid %{public}s is identical bind.", GetAnonyString(udid).c_str());
                return DM_OK;
            }
        }
    }
    return ERR_DM_FAILED;
}

DM_EXPORT int32_t DeviceProfileConnector::CheckIsSameAccountByUdidHash(const std::string &udidHash)
{
    if (udidHash.empty()) {
        LOGE("udidHash is empty!");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    std::vector<AccessControlProfile> profiles = GetAccessControlProfile();
    for (auto &item : profiles) {
        if (Crypto::GetUdidHash(item.GetTrustDeviceId()) == udidHash) {
            if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
                LOGI("The udidHash %{public}s is identical bind.", GetAnonyString(udidHash).c_str());
                return DM_OK;
            }
        }
    }
    return ERR_DM_VERIFY_SAME_ACCOUNT_FAILED;
}

bool checkAccesserACL(AccessControlProfile& profile, const DmAccessCaller &caller,
    const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    if ((profile.GetAccesser().GetAccesserUserId() == caller.userId ||
        profile.GetAccesser().GetAccesserUserId() == 0 ||
        profile.GetAccesser().GetAccesserUserId() == -1) &&
        profile.GetAccesser().GetAccesserDeviceId() == srcUdid &&
        profile.GetAccessee().GetAccesseeDeviceId() == sinkUdid) {
        if (callee.userId != 0 && callee.userId == profile.GetAccessee().GetAccesseeUserId()) {
            LOGI("accesser success add, callee userId not null!");
            return true;
        } else if (callee.userId == 0 ||
            profile.GetAccessee().GetAccesseeUserId() == -1 ||
            profile.GetAccessee().GetAccesseeUserId() == 0) {
            LOGI("accesser success add!");
            return true;
        }
    }
    return false;
}

bool checkAccesseeACL(AccessControlProfile& profile, const DmAccessCaller &caller,
    const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    if ((profile.GetAccessee().GetAccesseeUserId() == caller.userId ||
        profile.GetAccessee().GetAccesseeUserId() == 0 ||
        profile.GetAccessee().GetAccesseeUserId() == -1) &&
        profile.GetAccessee().GetAccesseeDeviceId() == srcUdid &&
        profile.GetAccesser().GetAccesserDeviceId() == sinkUdid) {
        if (callee.userId != 0 && callee.userId == profile.GetAccesser().GetAccesserUserId()) {
            LOGI("accessee success add, callee userId not null!");
            return true;
        } else if (callee.userId == 0 ||
            profile.GetAccesser().GetAccesserUserId() == -1 ||
            profile.GetAccesser().GetAccesserUserId() == 0) {
            LOGI("accessee success add!");
            return true;
        }
    }
    return false;
}

std::vector<AccessControlProfile> GetACLByDeviceIdAndUserId(std::vector<AccessControlProfile> profiles,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid = %{public}s, caller.userId = %{public}s, sinkUdid = %{public}s, callee.userId = %{public}s",
        GetAnonyString(srcUdid).c_str(), GetAnonyInt32(caller.userId).c_str(),
        GetAnonyString(sinkUdid).c_str(), GetAnonyInt32(callee.userId).c_str());
    std::vector<AccessControlProfile> profilesFilter;
    for (auto &item : profiles) {
        if (checkAccesserACL(item, caller, srcUdid, callee, sinkUdid) ||
            checkAccesseeACL(item, caller, srcUdid, callee, sinkUdid)) {
            profilesFilter.push_back(item);
        }
    }
    return profilesFilter;
}

DM_EXPORT bool DeviceProfileConnector::CheckAccessControl(
    const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s, srcAccountId %{public}s,"
        "sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s, sinkAccountId %{public}s"
        "callerTokenId %{public}s, calleeTokenId %{public}s.", GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str(), GetAnonyUint64(caller.tokenId).c_str(),
        GetAnonyUint64(callee.tokenId).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::vector<AccessControlProfile> profilesFilter =
        GetACLByDeviceIdAndUserId(profiles, caller, srcUdid, callee, sinkUdid);
    for (auto &item : profilesFilter) {
        if (item.GetStatus() != ACTIVE || (item.GetTrustDeviceId() != sinkUdid &&
            item.GetTrustDeviceId() != srcUdid)) {
            continue;
        }
        if (SingleUserProcess(item, caller, callee)) {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::SingleUserProcess(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const DmAccessCallee &callee)
{
    LOGI("BindType %{public}d, bindLevel %{public}d.",
        profile.GetBindType(), profile.GetBindLevel());
    uint32_t bindType = profile.GetBindType();
    bool ret = false;
    switch (bindType) {
        case DM_IDENTICAL_ACCOUNT:
            ret = true;
            break;
        case DM_POINT_TO_POINT:
            if (profile.GetBindLevel() == USER && !IsLnnAcl(profile)) {
                ret = true;
            } else if ((profile.GetBindLevel() == APP || profile.GetBindLevel() == SERVICE) &&
                (profile.GetAccesser().GetAccesserBundleName() == caller.pkgName ||
                profile.GetAccessee().GetAccesseeBundleName() == caller.pkgName)) {
                ret = CheckAppLevelAccess(profile, caller, callee);
            }
            break;
        case DM_ACROSS_ACCOUNT:
            if (profile.GetBindLevel() == USER && !IsLnnAcl(profile)) {
                ret = true;
            } else if ((profile.GetBindLevel() == APP || profile.GetBindLevel() == SERVICE) &&
                (profile.GetAccesser().GetAccesserBundleName() == caller.pkgName ||
                profile.GetAccessee().GetAccesseeBundleName() == caller.pkgName)) {
                ret = CheckAppLevelAccess(profile, caller, callee);
            }
            break;
        default:
            LOGE("unknown bind type %{public}d.", bindType);
            break;
    }
    return ret;
}

bool DeviceProfileConnector::CheckAppLevelAccess(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const DmAccessCallee &callee)
{
    if (caller.tokenId == 0 || callee.tokenId == 0) {
        return true;
    } else {
        if ((static_cast<uint64_t>(profile.GetAccesser().GetAccesserTokenId()) == caller.tokenId &&
            static_cast<uint64_t>(profile.GetAccessee().GetAccesseeTokenId()) == callee.tokenId) ||
            (static_cast<uint64_t>(profile.GetAccesser().GetAccesserTokenId()) == callee.tokenId &&
            static_cast<uint64_t>(profile.GetAccessee().GetAccesseeTokenId()) == caller.tokenId)) {
            return true;
        } else {
            return false;
        }
    }
}

DM_EXPORT bool DeviceProfileConnector::CheckIsSameAccount(
    const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s,"
        "srcAccountId %{public}s, sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s,"
        "sinkAccountId %{public}s, callerTokenId %{public}s, calleeTokenId %{public}s.",
        GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str(), GetAnonyUint64(caller.tokenId).c_str(),
        GetAnonyUint64(callee.tokenId).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::vector<AccessControlProfile> profilesFilter
        = GetACLByDeviceIdAndUserId(profiles, caller, srcUdid, callee, sinkUdid);
    for (auto &item : profilesFilter) {
        if (item.GetStatus() != ACTIVE || (item.GetTrustDeviceId() != sinkUdid &&
            item.GetTrustDeviceId() != srcUdid)) {
            continue;
        }
        if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
            LOGI("The udid %{public}s is identical bind.", GetAnonyString(item.GetTrustDeviceId()).c_str());
            return true;
        }
    }
    return false;
}

DM_EXPORT int32_t DeviceProfileConnector::GetBindLevel(const std::string &pkgName,
    const std::string &localUdid, const std::string &udid, uint64_t &tokenId)
{
    LOGI("pkgName %{public}s, udid %{public}s.", pkgName.c_str(), GetAnonyString(udid).c_str());
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localUdid,
        MultipleUserConnector::GetFirstForegroundUserId());
    int32_t bindLevel = INVALIED_TYPE;
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != udid) {
            continue;
        }
        if (item.GetAccesser().GetAccesserBundleName() == pkgName &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == udid) {
            tokenId = static_cast<uint64_t>(item.GetAccesser().GetAccesserTokenId());
            bindLevel = static_cast<int32_t>(item.GetBindLevel());
            LOGI("Src get bindLevel %{public}d.", bindLevel);
            continue;
        }
        if (item.GetAccessee().GetAccesseeBundleName() == pkgName &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == udid) {
            tokenId = static_cast<uint64_t>(item.GetAccessee().GetAccesseeTokenId());
            bindLevel = static_cast<int32_t>(item.GetBindLevel());
            LOGI("Sink get bindLevel %{public}d.", bindLevel);
            continue;
        }
    }
    return bindLevel;
}

std::map<std::string, int32_t> DeviceProfileConnector::GetDeviceIdAndBindLevel(std::vector<int32_t> userIds,
    const std::string &localUdid)
{
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::map<std::string, int32_t> deviceIdMap;
    for (const auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }
        if (find(userIds.begin(), userIds.end(), item.GetAccesser().GetAccesserUserId()) != userIds.end() &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid) {
            LOGI("Get Device Bind type localUdid %{public}s is src.", GetAnonyString(localUdid).c_str());
            UpdateBindType(item.GetTrustDeviceId(), item.GetBindLevel(), deviceIdMap);
            continue;
        }
        if (find(userIds.begin(), userIds.end(), item.GetAccessee().GetAccesseeUserId()) != userIds.end() &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid) {
            LOGI("Get Device Bind type localUdid %{public}s is sink.", GetAnonyString(localUdid).c_str());
            UpdateBindType(item.GetTrustDeviceId(), item.GetBindLevel(), deviceIdMap);
            continue;
        }
    }
    return deviceIdMap;
}

bool DeviceProfileConnector::CheckAccessControlProfileByTokenId(int32_t tokenId)
{
    if (tokenId < 0) {
        LOGE("tokenId error.");
        return false;
    }
    std::string localUdid = GetLocalDeviceId();
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    for (const auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == userId &&
            static_cast<int32_t>(item.GetAccesser().GetAccesserTokenId()) == tokenId) {
            return true;
        }
        if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeUserId() == userId &&
            static_cast<int32_t>(item.GetAccessee().GetAccesseeTokenId()) == tokenId) {
            return true;
        }
    }
    return false;
}

std::vector<std::string> DeviceProfileConnector::GetDeviceIdAndUdidListByTokenId(const std::vector<int32_t> &userIds,
    const std::string &localUdid, int32_t tokenId)
{
    if (userIds.empty() || localUdid.empty()) {
        LOGE("userIds or localUdid is empty.");
        return {};
    }
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::map<std::string, int32_t> deviceIdMap;
    std::vector<std::string> udidList;

    for (const auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }

        if (find(userIds.begin(), userIds.end(), item.GetAccesser().GetAccesserUserId()) != userIds.end() &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            static_cast<int32_t>(item.GetAccesser().GetAccesserTokenId()) == tokenId) {
            LOGI("Get Device Bind type localUdid %{public}s is src, tokenId %{public}s.",
                GetAnonyString(localUdid).c_str(), GetAnonyInt32(tokenId).c_str());
            UpdateBindType(item.GetTrustDeviceId(), item.GetBindLevel(), deviceIdMap);
            continue;
        }

        if (find(userIds.begin(), userIds.end(), item.GetAccessee().GetAccesseeUserId()) != userIds.end() &&
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            static_cast<int32_t>(item.GetAccessee().GetAccesseeTokenId()) == tokenId) {
            LOGI("Get Device Bind type localUdid %{public}s is sink, tokenId %{public}s.",
                GetAnonyString(localUdid).c_str(), GetAnonyInt32(tokenId).c_str());
            UpdateBindType(item.GetTrustDeviceId(), item.GetBindLevel(), deviceIdMap);
            continue;
        }
    }

    for (const auto &item : deviceIdMap) {
        udidList.push_back(item.first);
    }
    return udidList;
}

DM_EXPORT std::multimap<std::string, int32_t> DeviceProfileConnector::GetDeviceIdAndUserId(
    int32_t userId, const std::string &accountId, const std::string &localUdid)
{
    LOGI("localUdid %{public}s, userId %{public}d, accountId %{public}s.", GetAnonyString(localUdid).c_str(),
        userId, GetAnonyString(accountId).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::multimap<std::string, int32_t> deviceIdMap;
    for (const auto &item : profiles) {
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        std::string accesserAccountId = item.GetAccesser().GetAccesserAccountId();
        std::string accesseeAccountId = item.GetAccessee().GetAccesseeAccountId();
        if (accesserUdid == localUdid && accesserUserId == userId && accesserAccountId == accountId) {
            LOGI("Account logout trust udid %{public}s userid %{public}d is src.",
                GetAnonyString(accesseeUdid).c_str(), accesseeUserId);
            deviceIdMap.insert(std::pair<std::string, int32_t>(accesseeUdid, accesseeUserId));
            continue;
        }
        if (accesseeUdid == localUdid && accesseeUserId == userId && accesseeAccountId == accountId) {
            LOGI("Account logout trust udid %{public}s userid %{public}d is sink.",
                GetAnonyString(accesserUdid).c_str(), accesserUserId);
            deviceIdMap.insert(std::pair<std::string, int32_t>(accesserUdid, accesserUserId));
            continue;
        }
    }
    return deviceIdMap;
}

void DeviceProfileConnector::UpdateBindType(const std::string &udid, int32_t compareParam,
    std::map<std::string, int32_t> &deviceMap)
{
    LOGI("BindType %{public}d.", compareParam);
    if (deviceMap.find(udid) == deviceMap.end()) {
        deviceMap[udid] = compareParam;
    } else {
        deviceMap[udid] = std::min(deviceMap[udid], compareParam);
    }
}

int32_t DeviceProfileConnector::HandleAccountLogoutEvent(int32_t remoteUserId,
    const std::string &remoteAccountHash, const std::string &remoteUdid, const std::string &localUdid)
{
    LOGI("RemoteUserId %{public}d, remoteAccountHash %{public}s, remoteUdid %{public}s, localUdid %{public}s.",
        remoteUserId, GetAnonyString(remoteAccountHash).c_str(), GetAnonyString(remoteUdid).c_str(),
        GetAnonyString(localUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(remoteUserId);
    int32_t bindType = DM_INVALIED_TYPE;
    for (const auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == localUdid && accesseeUdid == remoteUdid && accesseeUserId == remoteUserId) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            bindType = DM_IDENTICAL_ACCOUNT;
            continue;
        }
        if (accesseeUdid == localUdid && accesserUdid == remoteUdid && accesserUserId == remoteUserId) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            bindType = DM_IDENTICAL_ACCOUNT;
            continue;
        }
    }
    return bindType;
}

DM_EXPORT int32_t DeviceProfileConnector::HandleDevUnBindEvent(int32_t remoteUserId, const std::string &remoteUdid,
    const std::string &localUdid, DmOfflineParam &offlineParam, int32_t tokenId)
{
    LOGI("RemoteUserId %{public}d, remoteUdid %{public}s, localUdid %{public}s, tokenId %{public}s.", remoteUserId,
        GetAnonyString(remoteUdid).c_str(), GetAnonyString(localUdid).c_str(), GetAnonyInt32(tokenId).c_str());
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(remoteUdid, remoteUserId, localUdid);
    int32_t bindType = DM_INVALIED_TYPE;
    for (const auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }
        if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
            bindType = DM_IDENTICAL_ACCOUNT;
            continue;
        }
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
            item.GetAccessee().GetAccesseeTokenId() == tokenId) {
            offlineParam.bindType = USER;
            CacheAcerAclId(item, offlineParam.needDelAclInfos);
            LOGI("Src delete acl bindType %{public}d, localUdid %{public}s, remoteUdid %{public}s", item.GetBindType(),
                GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str());
            bindType = std::min(bindType, static_cast<int32_t>(item.GetBindType()));
            continue;
        }
        if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
            item.GetAccesser().GetAccesserTokenId() == tokenId) {
            offlineParam.bindType = USER;
            CacheAceeAclId(item, offlineParam.needDelAclInfos);
            LOGI("Sink delete acl bindType %{public}u, localUdid %{public}s, remoteUdid %{public}s", item.GetBindType(),
                GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str());
            bindType = std::min(bindType, static_cast<int32_t>(item.GetBindType()));
            continue;
        }
    }
    return bindType;
}

DM_EXPORT DmOfflineParam DeviceProfileConnector::HandleAppUnBindEvent(int32_t remoteUserId,
    const std::string &remoteUdid, int32_t tokenId, const std::string &localUdid)
{
    LOGI("RemoteUserId %{public}d, remoteUdid %{public}s, localUdid %{public}s.",
        remoteUserId, GetAnonyString(remoteUdid).c_str(), GetAnonyString(localUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(remoteUdid, remoteUserId, localUdid);
    DmOfflineParam offlineParam;
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }

        // First, find need delete acl
        if (FindTargetAcl(item, localUdid, remoteUserId, remoteUdid, tokenId, offlineParam)) {
            continue;
        }

        // Second, find the LNN acl
        if (FindLnnAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Third, find the user or sameaccount acl, dertermine if report offline
        if (FindUserAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Fourth, find the left service/app acl, determine if del lnn acl
        if (FindLeftAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }
    }
    return offlineParam;
}

bool DeviceProfileConnector::FindTargetAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const int32_t remoteUserId, const std::string &remoteUdid,
    const int32_t tokenId, const int32_t peerTokenId, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    std::string acerDeviceId = acl.GetAccesser().GetAccesserDeviceId();
    std::string aceeDeviceId = acl.GetAccessee().GetAccesseeDeviceId();
    int32_t acerTokenId = static_cast<int32_t>(acl.GetAccesser().GetAccesserTokenId());
    int32_t aceeTokenId = static_cast<int32_t>(acl.GetAccessee().GetAccesseeTokenId());
    if (acl.GetAccesser().GetAccesserUserId() == remoteUserId && acerDeviceId == remoteUdid &&
        aceeDeviceId == localUdid && (acerTokenId == peerTokenId) && (aceeTokenId == tokenId)) {
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
        processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
        offlineParam.processVec.push_back(processInfo);
        CacheAceeAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Src del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    if (acl.GetAccessee().GetAccesseeUserId() == remoteUserId && aceeDeviceId == remoteUdid &&
        acerDeviceId == localUdid && (aceeTokenId == peerTokenId) && (acerTokenId == tokenId)) {
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
        }
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
        processInfo.userId = acl.GetAccesser().GetAccesserUserId();
        offlineParam.processVec.push_back(processInfo);
        CacheAcerAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Sink del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    return isMatch;
}

DM_EXPORT DmOfflineParam DeviceProfileConnector::HandleAppUnBindEvent(int32_t remoteUserId,
    const std::string &remoteUdid, int32_t tokenId, const std::string &localUdid, int32_t peerTokenId)
{
    LOGI("RemoteUserId %{public}d, remoteUdid %{public}s, localUdid %{public}s.",
        remoteUserId, GetAnonyString(remoteUdid).c_str(), GetAnonyString(localUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(remoteUdid, remoteUserId, localUdid);
    DmOfflineParam offlineParam;
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }

        // First, find need delete acl
        if (FindTargetAcl(item, localUdid, remoteUserId, remoteUdid, tokenId, peerTokenId, offlineParam)) {
            continue;
        }

        // Second, find the LNN acl
        if (FindLnnAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Third, find the user or sameaccount acl, dertermine if report offline
        if (FindUserAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Fourth, find the left service/app acl, determine if del lnn acl
        if (FindLeftAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }
    }
    return offlineParam;
}

bool DeviceProfileConnector::FindTargetAcl(const DistributedDeviceProfile::AccessControlProfile &acl,
    const std::string &localUdid, const int32_t remoteUserId, const std::string &remoteUdid,
    const int32_t remoteTokenId, DmOfflineParam &offlineParam)
{
    bool isMatch = false;
    if (acl.GetAccesser().GetAccesserUserId() == remoteUserId &&
        acl.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
        (static_cast<int32_t>(acl.GetAccesser().GetAccesserTokenId()) == remoteTokenId) &&
        acl.GetAccessee().GetAccesseeDeviceId() == localUdid) {
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
        processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
        processInfo.tokenId = acl.GetAccessee().GetAccesseeTokenId();
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
            processInfo.tokenId = 0;
        }
        offlineParam.processVec.push_back(processInfo);
        CacheAceeAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Src del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    if (acl.GetAccessee().GetAccesseeUserId() == remoteUserId &&
        acl.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
        (static_cast<int32_t>(acl.GetAccessee().GetAccesseeTokenId()) == remoteTokenId) &&
        acl.GetAccesser().GetAccesserDeviceId() == localUdid) {
        ProcessInfo processInfo;
        processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
        processInfo.userId = acl.GetAccesser().GetAccesserUserId();
        processInfo.tokenId = acl.GetAccesser().GetAccesserTokenId();
        if ((acl.GetBindLevel() == USER || acl.GetBindType() == DM_IDENTICAL_ACCOUNT)) {
            offlineParam.hasUserAcl = true;
            processInfo.tokenId = 0;
        }
        offlineParam.processVec.push_back(processInfo);
        CacheAcerAclId(acl, offlineParam.needDelAclInfos);
        LOGI("Sink del acl aclId: %{public}" PRId64 ", localUdid %{public}s, remoteUdid %{public}s"
            ", bindType %{public}d, bindLevel: %{public}d", acl.GetAccessControlId(),
            GetAnonyString(localUdid).c_str(), GetAnonyString(remoteUdid).c_str(), acl.GetBindType(),
            acl.GetBindLevel());
        isMatch = true;
    }
    return isMatch;
}

DmOfflineParam DeviceProfileConnector::HandleServiceUnBindEvent(int32_t remoteUserId,
    const std::string &remoteUdid, const std::string &localUdid, int32_t tokenId)
{
    LOGI("RemoteUserId %{public}d, remoteUdid %{public}s, localUdid %{public}s.",
        remoteUserId, GetAnonyString(remoteUdid).c_str(), GetAnonyString(localUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(remoteUdid, remoteUserId, localUdid);
    DmOfflineParam offlineParam;
    if (profiles.empty()) {
        LOGE("Acl is empty.");
        return offlineParam;
    }
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != remoteUdid) {
            continue;
        }

        // First, find need delete acl
        if (FindTargetAcl(item, localUdid, remoteUserId, remoteUdid, tokenId, offlineParam)) {
            continue;
        }

        // Second, find the LNN acl
        if (FindLnnAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Third, find the user or sameaccount acl, dertermine if report offline
        if (FindUserAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }

        // Fourth, find the left service/app acl, determine if del lnn acl
        if (FindLeftAcl(item, localUdid, remoteUdid, offlineParam)) {
            continue;
        }
    }
    return offlineParam;
}

//LCOV_EXCL_START
DM_EXPORT std::vector<AccessControlProfile> DeviceProfileConnector::GetAllAccessControlProfile()
{
    std::vector<AccessControlProfile> profiles;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetAllAccessControlProfile(profiles);
    if (ret != DM_OK) {
        LOGE("DP failed, ret = %{public}d", ret);
    }
    return profiles;
}

DM_EXPORT std::vector<AccessControlProfile> DeviceProfileConnector::GetAllAclIncludeLnnAcl()
{
    std::vector<AccessControlProfile> profiles;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetAllAclIncludeLnnAcl(profiles);
    if (ret != DM_OK) {
        LOGE("DP failed, ret = %{public}d", ret);
    }
    return profiles;
}
//LCOV_EXCL_STOP

DM_EXPORT void DeviceProfileConnector::DeleteAccessControlById(
    int64_t accessControlId)
{
    DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(accessControlId);
}

DM_EXPORT int32_t DeviceProfileConnector::HandleUserSwitched(
    const std::string &localUdid, const std::vector<std::string> &deviceVec, int32_t currentUserId,
    int32_t beforeUserId)
{
    if (deviceVec.empty()) {
        LOGI("no remote device.");
        return DM_OK;
    }
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::vector<AccessControlProfile> activeProfiles;
    std::vector<AccessControlProfile> inActiveProfiles;
    for (auto &item : profiles) {
        if (std::find(deviceVec.begin(), deviceVec.end(), item.GetTrustDeviceId()) == deviceVec.end()) {
            continue;
        }
        if ((item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == beforeUserId) ||
            (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeUserId() == beforeUserId)) {
            if (item.GetStatus() == ACTIVE) {
                item.SetStatus(INACTIVE);
                inActiveProfiles.push_back(item);
            }
            continue;
        }
        if ((item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == currentUserId && item.GetStatus() == INACTIVE) || (
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeUserId() == currentUserId && item.GetStatus() == INACTIVE)) {
            item.SetStatus(ACTIVE);
            activeProfiles.push_back(item);
            continue;
        }
    }
    HandleUserSwitched(activeProfiles, inActiveProfiles);
    return DM_OK;
}

DM_EXPORT void DeviceProfileConnector::HandleUserSwitched(
    const std::vector<AccessControlProfile> &activeProfiles,
    const std::vector<AccessControlProfile> &inActiveProfiles)
{
    for (auto &item : inActiveProfiles) {
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
    }
    for (auto &item : activeProfiles) {
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
    }
}

std::vector<AccessControlProfile> DeviceProfileConnector::GetAclProfileByUserId(const std::string &localUdid,
    int32_t userId, const std::string &remoteUdid)
{
    LOGI("localUdid %{public}s, localUserId %{public}d, remoteUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        userId, GetAnonyString(remoteUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::vector<AccessControlProfile> profilesTemp;
    for (const auto &item : profiles) {
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == userId &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid) {
            profilesTemp.push_back(item);
        } else if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeUserId() == userId &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid) {
            profilesTemp.push_back(item);
        }
    }
    return profilesTemp;
}

DM_EXPORT void DeviceProfileConnector::HandleSyncForegroundUserIdEvent(
    const std::vector<int32_t> &remoteUserIds, const std::string &remoteUdid,
    const std::vector<int32_t> &localUserIds, std::string &localUdid,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("localUdid %{public}s, remoteUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        GetAnonyString(remoteUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccessee().GetAccesseeDeviceId() == remoteUdid &&
            find(localUserIds.begin(), localUserIds.end(),
            item.GetAccesser().GetAccesserUserId()) != localUserIds.end() &&
            find(remoteUserIds.begin(), remoteUserIds.end(),
                item.GetAccessee().GetAccesseeUserId()) != remoteUserIds.end() && item.GetStatus() == INACTIVE) {
            item.SetStatus(ACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
            if (IsLnnAcl(item)) {
                continue;
            }
            DmUserRemovedServiceInfo serviceInfo;
            std::string aceeExtraData = item.GetAccessee().GetAccesseeExtraData();
            if (aceeExtraData.empty()) {
                LOGE("CheckAclByUdidAndTokenIdAndServiceId aceeExtraData is empty.");
                continue;
            }
            JsonObject aceeExtJson(aceeExtraData);
            if (aceeExtJson.IsDiscarded() || !IsArray(aceeExtJson, "serviceId")) {
                LOGE("serviceId is not exist.");
                continue;
            }
            JsonItemObject serviceIdItem = aceeExtJson["serviceId"];
            serviceIdItem.Get(serviceInfo.serviceIds);
            serviceInfo.localTokenId = item.GetAccesser().GetAccesserTokenId();
            serviceInfo.localPkgName = item.GetAccesser().GetAccesserBundleName();
            serviceInfo.bindType = item.GetBindType();
            serviceInfo.peerUdid = item.GetAccessee().GetAccesseeDeviceId();
            serviceInfo.peerUserId = item.GetAccessee().GetAccesseeUserId();
            serviceInfo.isActive = true;
            serviceInfos.push_back(serviceInfo);
        } else if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == remoteUdid &&
            find(localUserIds.begin(), localUserIds.end(),
            item.GetAccessee().GetAccesseeUserId()) != localUserIds.end() &&
            find(remoteUserIds.begin(), remoteUserIds.end(),
                item.GetAccesser().GetAccesserUserId()) != remoteUserIds.end() && item.GetStatus() == INACTIVE) {
            item.SetStatus(ACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        }
    }
}

std::vector<ProcessInfo> DeviceProfileConnector::GetOfflineProcessInfo(std::string &localUdid,
    const std::vector<int32_t> &localUserIds, const std::string &remoteUdid, const std::vector<int32_t> &remoteUserIds)
{
    LOGI("localUdid %{public}s, remoteUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        GetAnonyString(remoteUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::vector<ProcessInfo> processInfos;
    int32_t bindLevel = 100;
    for (const auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }
        ProcessInfo processInfo;
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == localUdid && accesseeUdid == remoteUdid &&
            find(localUserIds.begin(), localUserIds.end(), accesserUserId) != localUserIds.end() &&
            find(remoteUserIds.begin(), remoteUserIds.end(), accesseeUserId) != remoteUserIds.end() &&
            item.GetStatus() == ACTIVE) {
            processInfo.pkgName = item.GetAccesser().GetAccesserBundleName();
            processInfo.userId = item.GetAccesser().GetAccesserUserId();
            bindLevel = std::min(bindLevel, static_cast<int32_t>(item.GetBindLevel()));
            processInfos.push_back(processInfo);
        } else if (accesseeUdid == localUdid && accesserUdid == remoteUdid &&
            find(localUserIds.begin(), localUserIds.end(), accesseeUserId) != localUserIds.end() &&
            find(remoteUserIds.begin(), remoteUserIds.end(), accesserUserId) != remoteUserIds.end() &&
            item.GetStatus() == ACTIVE) {
            processInfo.pkgName = item.GetAccessee().GetAccesseeBundleName();
            processInfo.userId = item.GetAccessee().GetAccesseeUserId();
            bindLevel = std::min(bindLevel, static_cast<int32_t>(item.GetBindLevel()));
            processInfos.push_back(processInfo);
        }
    }
    if (bindLevel == INVALIED_TYPE || bindLevel == USER) {
        processInfos.clear();
        for (const auto &item : localUserIds) {
            ProcessInfo processInfo;
            processInfo.pkgName = std::string(DM_PKG_NAME);
            processInfo.userId = item;
            processInfos.push_back(processInfo);
        }
    }
    return processInfos;
}

DM_EXPORT std::map<int32_t, int32_t> DeviceProfileConnector::GetUserIdAndBindLevel(
    const std::string &localUdid, const std::string &peerUdid)
{
    LOGI("localUdid %{public}s, peerUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        GetAnonyString(peerUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::map<int32_t, int32_t> userIdAndBindLevel;
    for (const auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserid = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserid = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == localUdid && accesseeUdid == peerUdid) {
            if (userIdAndBindLevel.find(accesserUserid) == userIdAndBindLevel.end()) {
                userIdAndBindLevel[accesserUserid] = static_cast<int32_t>(item.GetBindLevel());
            } else {
                userIdAndBindLevel[accesserUserid] =
                    std::min(static_cast<int32_t>(item.GetBindLevel()), userIdAndBindLevel[accesserUserid]);
            }
        } else if (accesseeUdid == localUdid && accesserUdid == peerUdid) {
            if (userIdAndBindLevel.find(accesseeUserid) == userIdAndBindLevel.end()) {
                userIdAndBindLevel[accesseeUserid] = static_cast<int32_t>(item.GetBindLevel());
            } else {
                userIdAndBindLevel[accesseeUserid] =
                    std::min(static_cast<int32_t>(item.GetBindLevel()), userIdAndBindLevel[accesseeUserid]);
            }
        }
    }
    return userIdAndBindLevel;
}

DM_EXPORT void DeviceProfileConnector::UpdateACL(std::string &localUdid,
    const std::vector<int32_t> &localUserIds, const std::string &remoteUdid,
    const std::vector<int32_t> &remoteFrontUserIds, const std::vector<int32_t> &remoteBackUserIds,
    DmOfflineParam &offlineParam)
{
    LOGI("localUdid %{public}s, remoteUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        GetAnonyString(remoteUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto item : profiles) {
        // deleta signal trust acl.
        DeleteSigTrustACL(item, remoteUdid, remoteFrontUserIds, remoteBackUserIds, offlineParam);
        // update identical account userId.
        UpdatePeerUserId(item, localUdid, localUserIds, remoteUdid, remoteFrontUserIds);
    }
}

void DeviceProfileConnector::DeleteSigTrustACL(AccessControlProfile profile, const std::string &remoteUdid,
    const std::vector<int32_t> &remoteFrontUserIds, const std::vector<int32_t> &remoteBackUserIds,
    DmOfflineParam &offlineParam)
{
    LOGI("start.");
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t accesserUserid = profile.GetAccesser().GetAccesserUserId();
    int32_t accesseeUserid = profile.GetAccessee().GetAccesseeUserId();
    if (accesserUdid == remoteUdid && accesserUserid != 0 && accesserUserid != -1 &&
        find(remoteFrontUserIds.begin(), remoteFrontUserIds.end(), accesserUserid) == remoteFrontUserIds.end() &&
        find(remoteBackUserIds.begin(), remoteBackUserIds.end(), accesserUserid) == remoteBackUserIds.end()) {
        CacheAcerAclId(profile, offlineParam.needDelAclInfos);
        return;
    }
    if (accesseeUdid == remoteUdid && accesseeUserid != 0 && accesseeUserid != -1 &&
        find(remoteFrontUserIds.begin(), remoteFrontUserIds.end(), accesseeUserid) == remoteFrontUserIds.end() &&
        find(remoteBackUserIds.begin(), remoteBackUserIds.end(), accesseeUserid) == remoteBackUserIds.end()) {
        CacheAceeAclId(profile, offlineParam.needDelAclInfos);
        return;
    }
}

void DeviceProfileConnector::UpdatePeerUserId(AccessControlProfile profile, std::string &localUdid,
    const std::vector<int32_t> &localUserIds, const std::string &remoteUdid,
    const std::vector<int32_t> &remoteFrontUserIds)
{
    LOGI("start.");
    if (remoteFrontUserIds.empty() || localUserIds.empty()) {
        LOGI("remoteFrontUserIds or localUserIds is empty.");
        return;
    }
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t accesserUserid = profile.GetAccesser().GetAccesserUserId();
    int32_t accesseeUserid = profile.GetAccessee().GetAccesseeUserId();
    uint32_t bindType = profile.GetBindType();
    if (accesserUdid == localUdid && accesseeUdid == remoteUdid && bindType == DM_IDENTICAL_ACCOUNT &&
        find(localUserIds.begin(), localUserIds.end(), accesserUserid) != localUserIds.end() &&
        (accesseeUserid == 0 || accesseeUserid == -1)) {
        Accessee accessee = profile.GetAccessee();
        accessee.SetAccesseeUserId(remoteFrontUserIds[0]);
        profile.SetAccessee(accessee);
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
        return;
    }
}

void DeviceProfileConnector::SetProcessInfoPkgName(const DistributedDeviceProfile::AccessControlProfile &acl,
    std::vector<OHOS::DistributedHardware::ProcessInfo> &processInfoVec, bool isAccer)
{
    if (IsLnnAcl(acl)) {
        return;
    }
    OHOS::DistributedHardware::ProcessInfo processInfo;
    if (isAccer) {
        if (acl.GetBindType() == DM_IDENTICAL_ACCOUNT || acl.GetBindLevel() == USER) {
            processInfo.pkgName = std::string(DM_PKG_NAME);
        } else {
            processInfo.pkgName = acl.GetAccesser().GetAccesserBundleName();
            processInfo.tokenId = static_cast<uint32_t>(acl.GetAccesser().GetAccesserTokenId());
        }
        processInfo.userId = acl.GetAccesser().GetAccesserUserId();
    } else {
        if (acl.GetBindType() == DM_IDENTICAL_ACCOUNT || acl.GetBindLevel() == USER) {
            processInfo.pkgName = std::string(DM_PKG_NAME);
        } else {
            processInfo.pkgName = acl.GetAccessee().GetAccesseeBundleName();
            processInfo.tokenId = static_cast<uint32_t>(acl.GetAccessee().GetAccesseeTokenId());
        }
        processInfo.userId = acl.GetAccessee().GetAccesseeUserId();
    }
    auto check = [&processInfo](const OHOS::DistributedHardware::ProcessInfo &info) {
        return info.pkgName == processInfo.pkgName;
    };
    if (find_if(processInfoVec.begin(), processInfoVec.end(), check) != processInfoVec.end()) {
        return;
    }
    processInfoVec.emplace_back(processInfo);
}

DM_EXPORT std::multimap<std::string, int32_t> DeviceProfileConnector::GetDevIdAndUserIdByActHash(
    const std::string &localUdid, const std::string &peerUdid,
    int32_t peerUserId, const std::string &peerAccountHash)
{
    LOGI("localUdid %{public}s, peerUdid %{public}s, peerUserId %{public}d, peerAccountHash %{public}s.",
        GetAnonyString(localUdid).c_str(), GetAnonyString(peerUdid).c_str(), peerUserId, peerAccountHash.c_str());
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::multimap<std::string, int32_t> deviceIdMap;
    for (const auto &item : profiles) {
        std::string accesserAccountId = item.GetAccesser().GetAccesserAccountId();
        std::string accesseeAccountId = item.GetAccessee().GetAccesseeAccountId();
        char accesserAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
        if (Crypto::GetAccountIdHash(accesserAccountId, reinterpret_cast<uint8_t *>(accesserAccountIdHash)) != DM_OK) {
            LOGE("GetAccountHash failed.");
            return deviceIdMap;
        }
        char accesseeAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
        if (Crypto::GetAccountIdHash(accesseeAccountId, reinterpret_cast<uint8_t *>(accesseeAccountIdHash)) != DM_OK) {
            LOGE("GetAccountHash failed.");
            return deviceIdMap;
        }
        LOGI("accesserAccountIdHash %{public}s, accesseeAccountIdHash %{public}s", accesserAccountIdHash,
            accesseeAccountIdHash);
        std::string accesserUdid = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeUdid = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserid = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserid = item.GetAccessee().GetAccesseeUserId();
        if (accesserUdid == localUdid && accesseeUdid == peerUdid && accesseeUserid == peerUserId &&
            std::string(accesseeAccountIdHash) == peerAccountHash) {
            deviceIdMap.insert(std::pair<std::string, int32_t>(accesserUdid, accesserUserid));
            continue;
        }
        if (accesseeUdid == localUdid && accesserUdid == peerUdid && accesserUserid == peerUserId &&
            std::string(accesserAccountIdHash) == peerAccountHash) {
            deviceIdMap.insert(std::pair<std::string, int32_t>(accesseeUdid, accesseeUserid));
            continue;
        }
    }
    return deviceIdMap;
}

DM_EXPORT std::multimap<std::string, int32_t> DeviceProfileConnector::GetDeviceIdAndUserId(
    const std::string &localUdid, int32_t localUserId)
{
    LOGI("localUdid %{public}s, userId %{public}d.", GetAnonyString(localUdid).c_str(), localUserId);
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::multimap<std::string, int32_t> deviceIdMap;
    for (const auto &item : profiles) {
        std::string accesserDeviceId = item.GetAccesser().GetAccesserDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        std::string accesseeDeviceId = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserDeviceId == localUdid && accesserUserId == localUserId) {
            if (!IsValueExist(deviceIdMap, accesseeDeviceId, accesseeUserId)) {
                deviceIdMap.insert(std::pair<std::string, int32_t>(accesseeDeviceId, accesseeUserId));
            }
            continue;
        }
        if (accesseeDeviceId == localUdid && accesseeUserId == localUserId) {
            if (!IsValueExist(deviceIdMap, accesserDeviceId, accesserUserId)) {
                deviceIdMap.insert(std::pair<std::string, int32_t>(accesserDeviceId, accesserUserId));
            }
            continue;
        }
    }
    return deviceIdMap;
}

void DeviceProfileConnector::HandleSyncBackgroundUserIdEventInner(AccessControlProfile &item,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    if (item.GetStatus() == ACTIVE) {
        item.SetStatus(INACTIVE);
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        if (IsLnnAcl(item)) {
            return;
        }
        DmUserRemovedServiceInfo serviceInfo;
        std::string aceeExtraData = item.GetAccessee().GetAccesseeExtraData();
        if (aceeExtraData.empty()) {
            LOGE("CheckAclByUdidAndTokenIdAndServiceId aceeExtraData is empty.");
            return;
        }
        JsonObject aceeExtJson(aceeExtraData);
        if (aceeExtJson.IsDiscarded() || !IsArray(aceeExtJson, "serviceId")) {
            LOGE("serviceId is not exist.");
            return;
        }
        JsonItemObject serviceIdItem = aceeExtJson["serviceId"];
        serviceIdItem.Get(serviceInfo.serviceIds);
        serviceInfo.localTokenId = item.GetAccesser().GetAccesserTokenId();
        serviceInfo.localPkgName = item.GetAccesser().GetAccesserBundleName();
        serviceInfo.bindType = item.GetBindType();
        serviceInfo.peerUdid = item.GetAccessee().GetAccesseeDeviceId();
        serviceInfo.peerUserId = item.GetAccessee().GetAccesseeUserId();
        serviceInfos.push_back(serviceInfo);
    }
}

DM_EXPORT void DeviceProfileConnector::HandleSyncBackgroundUserIdEvent(
    const std::vector<int32_t> &remoteUserIds, const std::string &remoteUdid,
    const std::vector<int32_t> &localUserIds, std::string &localUdid,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("localUdid %{public}s, remoteUdid %{public}s.", GetAnonyString(localUdid).c_str(),
        GetAnonyString(remoteUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        std::string accesserDeviceId = item.GetAccesser().GetAccesserDeviceId();
        std::string accesseeDeviceId = item.GetAccessee().GetAccesseeDeviceId();
        int32_t accesserUserId = item.GetAccesser().GetAccesserUserId();
        int32_t accesseeUserId = item.GetAccessee().GetAccesseeUserId();
        if (accesserDeviceId == localUdid && accesseeDeviceId == remoteUdid &&
            (find(remoteUserIds.begin(), remoteUserIds.end(), accesseeUserId) != remoteUserIds.end() ||
            find(localUserIds.begin(), localUserIds.end(), accesserUserId) == localUserIds.end())) {
            HandleSyncBackgroundUserIdEventInner(item, serviceInfos);
        } else if ((accesseeDeviceId == localUdid && accesserDeviceId == remoteUdid) &&
            (find(remoteUserIds.begin(), remoteUserIds.end(), accesserUserId) != remoteUserIds.end() ||
            find(localUserIds.begin(), localUserIds.end(), accesseeUserId) == localUserIds.end())) {
            if (item.GetStatus() == ACTIVE) {
                item.SetStatus(INACTIVE);
                DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
            }
        }
    }
}

DM_EXPORT void DeviceProfileConnector::HandleDeviceUnBind(int32_t bindType,
    const std::string &peerUdid, const std::string &localUdid, int32_t localUserId, const std::string &localAccountId)
{
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles =
        DeviceProfileConnector::GetInstance().GetAllAccessControlProfile();
    if (profiles.empty()) {
        LOGI("profiles is empty");
        return;
    }
    for (auto &item : profiles) {
        if ((item.GetBindType() == static_cast<uint32_t>(bindType)) &&
            item.GetTrustDeviceId() == peerUdid &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserUserId() == localUserId &&
            item.GetAccesser().GetAccesserAccountId() == localAccountId) {
            DeviceProfileConnector::GetInstance().DeleteAccessControlById(item.GetAccessControlId());
        }
    }
}

DM_EXPORT int32_t DeviceProfileConnector::SubscribeDeviceProfileInited(
    sptr<DistributedDeviceProfile::IDpInitedCallback> dpInitedCallback)
{
    LOGI("In");
    if (dpInitedCallback == nullptr) {
        LOGE("dpInitedCallback is nullptr");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    int32_t ret = DistributedDeviceProfileClient::GetInstance().SubscribeDeviceProfileInited(
        DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID, dpInitedCallback);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::UnSubscribeDeviceProfileInited()
{
    LOGI("In");
    int32_t ret = DistributedDeviceProfileClient::GetInstance().UnSubscribeDeviceProfileInited(
        DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::PutAllTrustedDevices(
    const std::vector<DistributedDeviceProfile::TrustedDeviceInfo> &deviceInfos)
{
    LOGI("In deviceInfos.size:%{public}zu", deviceInfos.size());
    int32_t ret = DistributedDeviceProfileClient::GetInstance().PutAllTrustedDevices(deviceInfos);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

bool DeviceProfileConnector::CheckAclStatusNotMatch(const DistributedDeviceProfile::AccessControlProfile &profile,
    const std::string &localUdid, const std::vector<int32_t> &foregroundUserIds,
    const std::vector<int32_t> &backgroundUserIds)
{
    if ((profile.GetAccesser().GetAccesserDeviceId() == localUdid &&
        (find(backgroundUserIds.begin(), backgroundUserIds.end(), profile.GetAccesser().GetAccesserUserId()) !=
        backgroundUserIds.end()) && (profile.GetStatus() == ACTIVE)) ||
        (profile.GetAccessee().GetAccesseeDeviceId() == localUdid &&
        (find(backgroundUserIds.begin(), backgroundUserIds.end(), profile.GetAccessee().GetAccesseeUserId()) !=
        backgroundUserIds.end()) && (profile.GetStatus() == ACTIVE))) {
        return true;
    }
    if ((profile.GetAccesser().GetAccesserDeviceId() == localUdid &&
        (find(foregroundUserIds.begin(), foregroundUserIds.end(), profile.GetAccesser().GetAccesserUserId()) !=
        foregroundUserIds.end()) && profile.GetStatus() == INACTIVE) ||
        (profile.GetAccessee().GetAccesseeDeviceId() == localUdid &&
        (find(foregroundUserIds.begin(), foregroundUserIds.end(), profile.GetAccessee().GetAccesseeUserId()) !=
        foregroundUserIds.end()) && profile.GetStatus() == INACTIVE)) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckAclStatusAndForegroundNotMatch(const std::string &localUdid,
    const std::vector<int32_t> &foregroundUserIds, const std::vector<int32_t> &backgroundUserIds)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    LOGI("profiles size is %{public}zu", profiles.size());
    for (auto &item : profiles) {
        if (CheckAclStatusNotMatch(item, localUdid, foregroundUserIds, backgroundUserIds)) {
            return true;
        }
    }
    return false;
}

DM_EXPORT int32_t DeviceProfileConnector::HandleUserSwitched(
    const std::string &localUdid, const std::vector<std::string> &deviceVec,
    const std::vector<int32_t> &foregroundUserIds, const std::vector<int32_t> &backgroundUserIds)
{
    LOGI("OnStart HandleUserSwitched");
    if (deviceVec.empty()) {
        LOGI("no remote device.");
        return DM_OK;
    }
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::vector<AccessControlProfile> activeProfiles;
    std::vector<AccessControlProfile> inActiveProfiles;
    for (auto &item : profiles) {
        if (std::find(deviceVec.begin(), deviceVec.end(), item.GetTrustDeviceId()) == deviceVec.end()) {
            continue;
        }
        if ((item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            (find(backgroundUserIds.begin(), backgroundUserIds.end(),
            item.GetAccesser().GetAccesserUserId()) != backgroundUserIds.end())) ||
            (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            (find(backgroundUserIds.begin(), backgroundUserIds.end(),
            item.GetAccessee().GetAccesseeUserId()) != backgroundUserIds.end()))) {
            if (item.GetStatus() == ACTIVE) {
                item.SetStatus(INACTIVE);
                inActiveProfiles.push_back(item);
            }
            continue;
        }
        if ((item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            (find(foregroundUserIds.begin(), foregroundUserIds.end(),
            item.GetAccesser().GetAccesserUserId()) != foregroundUserIds.end()) && item.GetStatus() == INACTIVE) || (
            item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            (find(foregroundUserIds.begin(), foregroundUserIds.end(),
            item.GetAccessee().GetAccesseeUserId()) != foregroundUserIds.end()) && item.GetStatus() == INACTIVE)) {
            item.SetStatus(ACTIVE);
            activeProfiles.push_back(item);
            continue;
        }
    }
    HandleUserSwitched(activeProfiles, inActiveProfiles);
    return DM_OK;
}

int32_t DeviceProfileConnector::HandleUserStop(int32_t stopUserId, const std::string &stopEventUdid)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if ((item.GetAccesser().GetAccesserDeviceId() == stopEventUdid &&
            item.GetAccesser().GetAccesserUserId() == stopUserId && item.GetStatus() == ACTIVE) ||
            (item.GetAccessee().GetAccesseeDeviceId() == stopEventUdid &&
            item.GetAccessee().GetAccesseeUserId() == stopUserId && item.GetStatus() == ACTIVE)) {
            item.SetStatus(INACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        }
    }
    return DM_OK;
}

int32_t DeviceProfileConnector::HandleUserStop(int32_t stopUserId, const std::string &stopEventUdid,
    const std::vector<std::string> &acceptEventUdids)
{
    if (acceptEventUdids.empty()) {
        LOGI("no remote device.");
        return DM_OK;
    }
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if (std::find(acceptEventUdids.begin(), acceptEventUdids.end(), item.GetTrustDeviceId()) ==
            acceptEventUdids.end()) {
            continue;
        }
        if ((item.GetAccesser().GetAccesserDeviceId() == stopEventUdid &&
            item.GetAccesser().GetAccesserUserId() == stopUserId && item.GetStatus() == ACTIVE) ||
            (item.GetAccessee().GetAccesseeDeviceId() == stopEventUdid &&
            item.GetAccessee().GetAccesseeUserId() == stopUserId && item.GetStatus() == ACTIVE)) {
            item.SetStatus(INACTIVE);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
        }
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::UpdateAclDeviceName(const std::string &udid,
    const std::string &newDeviceName, bool isLocal)
{
    std::vector<AccessControlProfile> allProfile =
        DeviceProfileConnector::GetInstance().GetAllAccessControlProfile();
    int32_t localUserId = MultipleUserConnector::GetCurrentAccountUserID();
    for (AccessControlProfile profile : allProfile) {
        if (!isLocal && profile.GetTrustDeviceId() != udid) {
            continue;
        }
        if (profile.GetStatus() != ACTIVE) {
            continue;
        }
        Accessee acee = profile.GetAccessee();
        Accesser acer = profile.GetAccesser();
        if (acee.GetAccesseeDeviceId() == udid && ((!isLocal && acer.GetAccesserUserId() == localUserId) ||
            (isLocal && acee.GetAccesseeUserId() == localUserId))) {
            acee.SetAccesseeDeviceName(newDeviceName);
            profile.SetAccessee(acee);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
            continue;
        }
        if (acer.GetAccesserDeviceId() == udid && ((!isLocal && acee.GetAccesseeUserId() == localUserId) ||
            (isLocal && acer.GetAccesserUserId() == localUserId))) {
            acer.SetAccesserDeviceName(newDeviceName);
            profile.SetAccesser(acer);
            DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
            continue;
        }
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::CheckDeviceInfoPermission(const std::string &localUdid,
    const std::string &peerDeviceId)
{
    LOGI("Start.");
    int32_t localUserId = 0;
    uint32_t tempLocalTokenId = 0;
    MultipleUserConnector::GetTokenIdAndForegroundUserId(tempLocalTokenId, localUserId);
    int64_t localTokenId = static_cast<int64_t>(tempLocalTokenId);
    std::string localAccountId = MultipleUserConnector::GetOhosAccountIdByUserId(localUserId);
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(localUserId);
    for (auto &item : profiles) {
        if (IsLnnAcl(item)) {
            continue;
        }
        if (item.GetTrustDeviceId() == peerDeviceId) {
            if (item.GetBindType() == DM_IDENTICAL_ACCOUNT || item.GetBindLevel() == USER) {
                return DM_OK;
            }
        }
        int32_t profileUserId = item.GetAccesser().GetAccesserUserId();
        if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
            (profileUserId == localUserId || profileUserId == -1 || profileUserId == 0) &&
            item.GetAccesser().GetAccesserTokenId() == localTokenId &&
            item.GetAccessee().GetAccesseeDeviceId() == peerDeviceId) {
            return DM_OK;
        }
        profileUserId = item.GetAccessee().GetAccesseeUserId();
        if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            (profileUserId == localUserId || profileUserId == -1 || profileUserId == 0) &&
            item.GetAccessee().GetAccesseeTokenId() == localTokenId &&
            item.GetAccesser().GetAccesserDeviceId() == peerDeviceId) {
            return DM_OK;
        }
    }
    return ERR_DM_NO_PERMISSION;
}

DM_EXPORT int32_t DeviceProfileConnector::PutLocalServiceInfo(
    const DistributedDeviceProfile::LocalServiceInfo &localServiceInfo)
{
    int32_t ret = DistributedDeviceProfileClient::GetInstance().PutLocalServiceInfo(localServiceInfo);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::DeleteLocalServiceInfo(const std::string &bundleName, int32_t pinExchangeType)
{
    int32_t ret = DistributedDeviceProfileClient::GetInstance().DeleteLocalServiceInfo(bundleName, pinExchangeType);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::UpdateLocalServiceInfo(
    const DistributedDeviceProfile::LocalServiceInfo &localServiceInfo)
{
    int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateLocalServiceInfo(localServiceInfo);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::GetLocalServiceInfoByBundleNameAndPinExchangeType(
    const std::string &bundleName, int32_t pinExchangeType,
    DistributedDeviceProfile::LocalServiceInfo &localServiceInfo)
{
    LOGI("getLocalServiceInfo bundleName = %{public}s, pinExchangeType = %{public}d",
        bundleName.c_str(), pinExchangeType);
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetLocalServiceInfoByBundleAndPinType(bundleName,
        pinExchangeType, localServiceInfo);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

int32_t DeviceProfileConnector::PutSessionKey(int32_t userId, const std::vector<unsigned char> &sessionKeyArray,
    int32_t &sessionKeyId)
{
    if (sessionKeyArray.empty() || sessionKeyArray.size() > MAX_SESSION_KEY_LENGTH) {
        LOGE("SessionKey size invalid");
        return ERR_DM_FAILED;
    }
    int32_t ret = DistributedDeviceProfileClient::GetInstance().PutSessionKey(static_cast<uint32_t>(userId),
        sessionKeyArray, sessionKeyId);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

int32_t DeviceProfileConnector::DeleteSessionKey(int32_t userId, int32_t sessionKeyId)
{
    int32_t ret =
        DistributedDeviceProfileClient::GetInstance().DeleteSessionKey(static_cast<uint32_t>(userId), sessionKeyId);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

int32_t DeviceProfileConnector::GetSessionKey(int32_t userId, int32_t sessionKeyId,
    std::vector<unsigned char> &sessionKeyArray)
{
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetSessionKey(static_cast<uint32_t>(userId),
        sessionKeyId, sessionKeyArray);
    if (ret != DM_OK) {
        LOGE("failed: %{public}d", ret);
        return ret;
    }
    return DM_OK;
}

DM_EXPORT bool DeviceProfileConnector::IsLnnAcl(const DistributedDeviceProfile::AccessControlProfile &profile)
{
    std::string extraData = profile.GetExtraData();
    if (extraData.empty()) {
        return false;
    }

    JsonObject extJson(extraData);
    if (extJson.IsDiscarded() || !IsString(extJson, ACL_IS_LNN_ACL_KEY)) {
        return false;
    }

    std::string isLnnAclStr = extJson[ACL_IS_LNN_ACL_KEY].Get<std::string>();
    std::string isLnnAclTrue = std::string(ACL_IS_LNN_ACL_VAL_TRUE);
    return isLnnAclStr == isLnnAclTrue;
}

DM_EXPORT void DeviceProfileConnector::CacheAcerAclId(const DistributedDeviceProfile::AccessControlProfile &profile,
    std::vector<DmAclIdParam> &aclInfos)
{
    DmAclIdParam dmAclIdParam;
    dmAclIdParam.udid = profile.GetAccesser().GetAccesserDeviceId();
    dmAclIdParam.userId = profile.GetAccesser().GetAccesserUserId();
    dmAclIdParam.skId = profile.GetAccesser().GetAccesserSessionKeyId();
    dmAclIdParam.credId = profile.GetAccesser().GetAccesserCredentialIdStr();
    dmAclIdParam.tokenIds.insert(profile.GetAccessee().GetAccesseeTokenId());
    dmAclIdParam.tokenIds.insert(profile.GetAccesser().GetAccesserTokenId());
    dmAclIdParam.pkgName = profile.GetAccesser().GetAccesserBundleName();
    dmAclIdParam.accessControlId = profile.GetAccessControlId();
    aclInfos.push_back(dmAclIdParam);
}

DM_EXPORT void DeviceProfileConnector::CacheAceeAclId(const DistributedDeviceProfile::AccessControlProfile &profile,
    std::vector<DmAclIdParam> &aclInfos)
{
    DmAclIdParam dmAclIdParam;
    dmAclIdParam.udid = profile.GetAccessee().GetAccesseeDeviceId();
    dmAclIdParam.userId = profile.GetAccessee().GetAccesseeUserId();
    dmAclIdParam.skId = profile.GetAccessee().GetAccesseeSessionKeyId();
    dmAclIdParam.credId = profile.GetAccessee().GetAccesseeCredentialIdStr();
    dmAclIdParam.tokenIds.insert(profile.GetAccessee().GetAccesseeTokenId());
    dmAclIdParam.tokenIds.insert(profile.GetAccesser().GetAccesserTokenId());
    dmAclIdParam.accessControlId = profile.GetAccessControlId();
    dmAclIdParam.pkgName = profile.GetAccessee().GetAccesseeBundleName();
    aclInfos.push_back(dmAclIdParam);
}

DmUserRemovedServiceInfo ParseServiceInfoForProfile(const AccessControlProfile &item, bool isActive)
{
    DmUserRemovedServiceInfo serviceInfo;
    std::string aceeExtraData = item.GetAccessee().GetAccesseeExtraData();
    if (aceeExtraData.empty()) {
        LOGE("CheckAclByUdidAndTokenIdAndServiceId aceeExtraData is empty.");
        return serviceInfo;
    }
    JsonObject aceeExtJson(aceeExtraData);
    if (aceeExtJson.IsDiscarded() || !IsArray(aceeExtJson, "serviceId")) {
        LOGE("serviceId is not exist.");
        return serviceInfo;
    }
    JsonItemObject serviceIdItem = aceeExtJson["serviceId"];
    serviceIdItem.Get(serviceInfo.serviceIds);
    serviceInfo.localTokenId = item.GetAccesser().GetAccesserTokenId();
    serviceInfo.localPkgName = item.GetAccesser().GetAccesserBundleName();
    serviceInfo.bindType = item.GetBindType();
    serviceInfo.peerUdid = item.GetAccessee().GetAccesseeDeviceId();
    serviceInfo.peerUserId = item.GetAccessee().GetAccesseeUserId();
    serviceInfo.isActive = isActive;
    return serviceInfo;
}

bool IsProfileForBackgroundUser(const AccessControlProfile &item, const std::string &localUdid,
    const std::vector<int32_t> &foregroundUserIds)
{
    if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
        std::find(foregroundUserIds.begin(), foregroundUserIds.end(), item.GetAccesser().GetAccesserUserId()) ==
        foregroundUserIds.end()) {
        return true;
    }
    if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
        std::find(foregroundUserIds.begin(), foregroundUserIds.end(), item.GetAccessee().GetAccesseeUserId()) ==
        foregroundUserIds.end()) {
        return true;
    }
    return false;
}

bool IsProfileForForegroundUser(const AccessControlProfile &item, const std::string &localUdid,
    const std::vector<int32_t> &foregroundUserIds)
{
    if (item.GetAccesser().GetAccesserDeviceId() == localUdid &&
        std::find(foregroundUserIds.begin(), foregroundUserIds.end(), item.GetAccesser().GetAccesserUserId()) !=
        foregroundUserIds.end()) {
        return true;
    }
    if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
        std::find(foregroundUserIds.begin(), foregroundUserIds.end(), item.GetAccessee().GetAccesseeUserId()) !=
        foregroundUserIds.end()) {
        return true;
    }
    return false;
}

DM_EXPORT int32_t DeviceProfileConnector::HandleAccountCommonEvent(const std::string &localUdid,
    const std::vector<std::string> &deviceVec, const std::vector<int32_t> &foregroundUserIds,
    const std::vector<int32_t> &backgroundUserIds, std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("start, foregroundUserIds: %{public}s, backgroundUserIds:  %{public}s",
        GetIntegerList(foregroundUserIds).c_str(), GetIntegerList(backgroundUserIds).c_str());
    if (deviceVec.empty()) {
        LOGI("no remote device.");
        return DM_OK;
    }
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::vector<AccessControlProfile> activeProfiles;
    std::vector<AccessControlProfile> inActiveProfiles;
    for (auto &item : profiles) {
        if (std::find(deviceVec.begin(), deviceVec.end(), item.GetTrustDeviceId()) == deviceVec.end()) {
            continue;
        }
        if (IsProfileForBackgroundUser(item, localUdid, foregroundUserIds) && item.GetStatus() == ACTIVE) {
            item.SetStatus(INACTIVE);
            inActiveProfiles.push_back(item);
            if (item.GetAccesser().GetAccesserDeviceId() != localUdid || IsLnnAcl(item)) {
                continue;
            }
            serviceInfos.push_back(ParseServiceInfoForProfile(item, false));
            continue;
        }
        if (IsProfileForForegroundUser(item, localUdid, foregroundUserIds) && item.GetStatus() == INACTIVE) {
            item.SetStatus(ACTIVE);
            activeProfiles.push_back(item);
            if (item.GetAccesser().GetAccesserDeviceId() != localUdid || IsLnnAcl(item)) {
                continue;
            }
            serviceInfos.push_back(ParseServiceInfoForProfile(item, true));
            continue;
        }
    }
    for (auto &item : inActiveProfiles) {
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
    }
    for (auto &item : activeProfiles) {
        DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(item);
    }
    return DM_OK;
}

DM_EXPORT bool DeviceProfileConnector::CheckSrcAccessControl(const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s,"
        "srcAccountId %{public}s, sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s,"
        "sinkAccountId %{public}s, callerTokenId %{public}s, calleeTokenId %{public}s.",
        GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str(), GetAnonyUint64(caller.tokenId).c_str(),
        GetAnonyUint64(callee.tokenId).c_str());
    if (!CheckUserIdIsForegroundUserId(caller.userId)) {
        LOGI("srcUserId = %{public}d is not foregroundUserId", caller.userId);
        return false;
    }
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::string localUdid = GetLocalDeviceId();
    std::string trustUdid = (localUdid == srcUdid ? sinkUdid : srcUdid);
    for (const auto &item : profiles) {
        PrintProfile(item);
        if (item.GetTrustDeviceId() != trustUdid) {
            continue;
        }
        switch (item.GetBindType()) {
            case DM_IDENTICAL_ACCOUNT:
                if (CheckSrcAcuntAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            case DM_SHARE:
                if (CheckSrcShareAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            case DM_POINT_TO_POINT:
            case DM_ACROSS_ACCOUNT:
                if (CheckSrcP2PAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            default:
                break;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckSrcAcuntAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    //bind type is identical account, accesser is caller, accessee is callee
    if (srcUdid == acerDeviceId && caller.userId == acerUserId && sinkUdid == aceeDeviceId) {
        return true;
    }
    //bind type is identical account, accessee is caller, accesser is callee
    if (srcUdid == aceeDeviceId && caller.userId == aceeUserId && sinkUdid == acerDeviceId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckSrcShareAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();
    std::string acerAccountId = profile.GetAccesser().GetAccesserAccountId();
    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    if (srcUdid == acerDeviceId && caller.userId == acerUserId && caller.accountId == acerAccountId &&
        sinkUdid == aceeDeviceId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckSrcP2PAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();
    int32_t acerTokenId = static_cast<int32_t>(profile.GetAccesser().GetAccesserTokenId());
    std::string acerPkgName = profile.GetAccesser().GetAccesserBundleName();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    int32_t aceeTokenId = static_cast<int32_t>(profile.GetAccessee().GetAccesseeTokenId());
    std::string aceePkgName = profile.GetAccessee().GetAccesseeBundleName();

    uint32_t bindLevel = profile.GetBindLevel();
    switch (bindLevel) {
        case USER:
            //bind level is user, accesser is caller, accessee is callee
            if (srcUdid == acerDeviceId && caller.userId == acerUserId && sinkUdid == aceeDeviceId) {
                return true;
            }
            //bind level is user, accessee is caller, accesser is callee
            if (srcUdid == aceeDeviceId && caller.userId == aceeUserId && sinkUdid == acerDeviceId) {
                return true;
            }
            break;
        case SERVICE:
        case APP:
            //bind level is user, accesser is caller, accessee is callee
            if (srcUdid == acerDeviceId && caller.userId == acerUserId &&
                static_cast<int32_t>(caller.tokenId) == acerTokenId && sinkUdid == aceeDeviceId) {
                return true;
            }
            //bind level is user, accessee is caller, accesser is callee
            if (srcUdid == aceeDeviceId && caller.userId == aceeUserId &&
                static_cast<int32_t>(caller.tokenId) == aceeTokenId && sinkUdid == acerDeviceId) {
                return true;
            }
            break;
        default:
            LOGE("invalid bindLevel %{public}d.", bindLevel);
            break;
    }
    return false;
}

DM_EXPORT bool DeviceProfileConnector::CheckSinkAccessControl(const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s,"
        "srcAccountId %{public}s, sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s,"
        "sinkAccountId %{public}s.", GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str());
    if (!CheckUserIdIsForegroundUserId(callee.userId)) {
        LOGI("sinkUserId = %{public}d is not ForegroundUserId", callee.userId);
        return false;
    }
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::string localUdid = GetLocalDeviceId();
    std::string trustUdid = (localUdid == srcUdid ? sinkUdid : srcUdid);
    for (const auto &item : profiles) {
        PrintProfile(item);
        if (item.GetTrustDeviceId() != trustUdid) {
            continue;
        }
        switch (item.GetBindType()) {
            case DM_IDENTICAL_ACCOUNT:
                if (CheckSinkAcuntAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            case DM_SHARE:
                if (CheckSinkShareAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            case DM_POINT_TO_POINT:
            case DM_ACROSS_ACCOUNT:
                if (CheckSinkP2PAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
                    return true;
                }
                break;
            default:
                break;
        }
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkAcuntAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();

    //bind type is identical account, accesser is caller, accessee is callee
    if (srcUdid == acerDeviceId && caller.userId == acerUserId &&
        sinkUdid == aceeDeviceId && callee.userId == aceeUserId && caller.accountId == callee.accountId) {
        return true;
    }

    //bind type is identical account, accessee is caller, accesser is callee
    if (srcUdid == aceeDeviceId && caller.userId == aceeUserId &&
        sinkUdid == acerDeviceId && callee.userId == acerUserId && caller.accountId == callee.accountId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkShareAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();
    std::string acerAccountId = profile.GetAccesser().GetAccesserAccountId();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    std::string aceeAccountId = profile.GetAccessee().GetAccesseeAccountId();
    if (srcUdid == acerDeviceId && caller.userId == acerUserId && caller.accountId == acerAccountId &&
        sinkUdid == aceeDeviceId && callee.userId == aceeUserId && callee.accountId == aceeAccountId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkP2PAccessControl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee, const std::string &sinkUdid)
{
    uint32_t bindLevel = profile.GetBindLevel();
    switch (bindLevel) {
        case USER:
            if (CheckSinkUserP2PAcl(profile, caller, srcUdid, callee, sinkUdid)) {
                return true;
            }
            break;
        case SERVICE:
        case APP:
            if (CheckSinkAppOrServiceP2PAcl(profile, caller, srcUdid, callee, sinkUdid)) {
                return true;
            }
            break;
        default:
            LOGE("invalid bindLevel %{public}d.", bindLevel);
            break;
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkUserP2PAcl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee,
    const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    //bind level is user, accesser is caller, accessee is callee
    if (srcUdid == acerDeviceId && caller.userId == acerUserId && sinkUdid == aceeDeviceId &&
        callee.userId == aceeUserId) {
        return true;
    }
    //bind level is user, accessee is caller, accesser is callee
    if (srcUdid == aceeDeviceId && caller.userId == aceeUserId && sinkUdid == acerDeviceId &&
        callee.userId == acerUserId) {
        return true;
    }
    return false;
}

bool DeviceProfileConnector::CheckSinkAppOrServiceP2PAcl(const DistributedDeviceProfile::AccessControlProfile &profile,
    const DmAccessCaller &caller, const std::string &srcUdid, const DmAccessCallee &callee,
    const std::string &sinkUdid)
{
    std::string acerDeviceId = profile.GetAccesser().GetAccesserDeviceId();
    int32_t acerUserId = profile.GetAccesser().GetAccesserUserId();
    int32_t acerTokenId = static_cast<int32_t>(profile.GetAccesser().GetAccesserTokenId());

    std::string aceeDeviceId = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t aceeUserId = profile.GetAccessee().GetAccesseeUserId();
    int32_t aceeTokenId = static_cast<int32_t>(profile.GetAccessee().GetAccesseeTokenId());
    //bind level is app or service, accesser is caller, accessee is callee
    if (srcUdid == acerDeviceId && caller.userId == acerUserId &&
        static_cast<int32_t>(caller.tokenId) == acerTokenId && sinkUdid == aceeDeviceId &&
        callee.userId == aceeUserId && static_cast<int32_t>(callee.tokenId) == aceeTokenId) {
        return true;
    }
    //bind level is app or service, accessee is caller, accesser is callee
    if (srcUdid == aceeDeviceId && caller.userId == aceeUserId &&
        static_cast<int32_t>(caller.tokenId) == aceeTokenId && sinkUdid == acerDeviceId &&
        callee.userId == acerUserId && static_cast<int32_t>(callee.tokenId) == acerTokenId) {
        return true;
    }
    return false;
}

DM_EXPORT bool DeviceProfileConnector::CheckSrcIsSameAccount(const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s,"
        "srcAccountId %{public}s, sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s,"
        "sinkAccountId %{public}s, callerTokenId %{public}s, calleeTokenId %{public}s.",
        GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str(), GetAnonyUint64(caller.tokenId).c_str(),
        GetAnonyUint64(callee.tokenId).c_str());
    if (!CheckUserIdIsForegroundUserId(caller.userId)) {
        LOGI("srcUserId = %{public}d is not ForegroundUserId", caller.userId);
        return false;
    }
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::string localUdid = GetLocalDeviceId();
    std::string trustUdid = (localUdid == srcUdid ? sinkUdid : srcUdid);
    for (const auto &item : profiles) {
        PrintProfile(item);
        if (item.GetTrustDeviceId() != trustUdid || item.GetBindType() != DM_IDENTICAL_ACCOUNT) {
            continue;
        }
        if (CheckSrcAcuntAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
            return true;
        }
    }
    return false;
}

DM_EXPORT bool DeviceProfileConnector::CheckSinkIsSameAccount(const DmAccessCaller &caller, const std::string &srcUdid,
    const DmAccessCallee &callee, const std::string &sinkUdid)
{
    LOGI("srcUdid %{public}s, srcUserId %{public}d, srcPkgName %{public}s,"
        "srcAccountId %{public}s, sinkUdid %{public}s, sinkUserId %{public}d, sinkPkgName %{public}s,"
        "sinkAccountId %{public}s, callerTokenId %{public}s, calleeTokenId %{public}s.",
        GetAnonyString(srcUdid).c_str(), caller.userId,
        caller.pkgName.c_str(), GetAnonyString(caller.accountId).c_str(),
        GetAnonyString(sinkUdid).c_str(), callee.userId, callee.pkgName.c_str(),
        GetAnonyString(callee.accountId).c_str(), GetAnonyUint64(caller.tokenId).c_str(),
        GetAnonyUint64(callee.tokenId).c_str());
    if (!CheckUserIdIsForegroundUserId(callee.userId)) {
        LOGI("sinkUserId = %{public}d is not ForegroundUserId", callee.userId);
        return false;
    }
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::string localUdid = GetLocalDeviceId();
    std::string trustUdid = (localUdid == srcUdid ? sinkUdid : srcUdid);
    for (const auto &item : profiles) {
        PrintProfile(item);
        if (item.GetTrustDeviceId() != trustUdid || item.GetBindType() != DM_IDENTICAL_ACCOUNT) {
            continue;
        }
        if (CheckSinkAcuntAccessControl(item, caller, srcUdid, callee, sinkUdid)) {
            return true;
        }
    }
    return false;
}

DM_EXPORT bool DeviceProfileConnector::CheckUserIdIsForegroundUserId(const int32_t userId)
{
    std::vector<int32_t> userVec;
    int32_t ret = MultipleUserConnector::GetForegroundUserIds(userVec);
    if (ret != DM_OK) {
        LOGE("GetForegroundUserIds failed, ret = %{public}d", ret);
        return false;
    }
    if (std::find(userVec.begin(), userVec.end(), userId) != userVec.end()) {
        return true;
    }
    LOGE("userId = %{public}d is not foregroundUserId.", userId);
    return false;
}

DM_EXPORT void DeviceProfileConnector::DeleteHoDevice(const std::string &peerUdid,
    const std::vector<int32_t> &foreGroundUserIds, const std::vector<int32_t> &backGroundUserIds)
{
    if (peerUdid.empty() || foreGroundUserIds.empty() || backGroundUserIds.empty()) {
        LOGE("invalid input param.");
        return;
    }
    std::vector<int32_t> localUserIds(foreGroundUserIds.begin(), foreGroundUserIds.end());
    std::copy(backGroundUserIds.begin(), backGroundUserIds.end(), std::back_inserter(localUserIds));
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    std::string localUdid = GetLocalDeviceId();
    for (const auto &item : profiles) {
        if (peerUdid != item.GetTrustDeviceId() || item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
            continue;
        }
        std::string acerDeviceId = item.GetAccesser().GetAccesserDeviceId();
        int32_t acerUserId = item.GetAccesser().GetAccesserUserId();
        std::string acerPkgName = item.GetAccesser().GetAccesserBundleName();
        std::string aceeDeviceId = item.GetAccessee().GetAccesseeDeviceId();
        int32_t aceeUserId = item.GetAccessee().GetAccesseeUserId();
        std::string aceePkgName = item.GetAccessee().GetAccesseeBundleName();

        if (localUdid == acerDeviceId && peerUdid == aceeDeviceId && !CheckExtWhiteList(acerPkgName) &&
            std::find(localUserIds.begin(), localUserIds.end(), acerUserId) != localUserIds.end()) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            continue;
        }
        if (peerUdid == acerDeviceId && localUdid == aceeDeviceId && !CheckExtWhiteList(aceePkgName) &&
            std::find(localUserIds.begin(), localUserIds.end(), aceeUserId) != localUserIds.end()) {
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item.GetAccessControlId());
            continue;
        }
    }
}

DM_EXPORT void DeviceProfileConnector::GetRemoteTokenIds(const std::string &localUdid,
    const std::string &udid, std::unordered_set<int64_t> &remoteTokenIds)
{
    if (udid.empty() || localUdid.empty() || localUdid == udid) {
        LOGE("udid error.");
        return;
    }
    int32_t userId = MultipleUserConnector::GetCurrentAccountUserID();
    std::vector<AccessControlProfile> profiles = GetAclProfileByDeviceIdAndUserId(localUdid, userId);
    uint64_t peerToken = 0;
    for (auto &item : profiles) {
        if (item.GetStatus() != ACTIVE) {
            continue;
        }
        if (item.GetAccessee().GetAccesseeDeviceId() == localUdid &&
            item.GetAccesser().GetAccesserDeviceId() == udid) {
            peerToken = static_cast<uint64_t>(item.GetAccesser().GetAccesserTokenId());
            remoteTokenIds.insert(peerToken);
        }
        if (item.GetAccessee().GetAccesseeDeviceId()== udid &&
            item.GetAccesser().GetAccesserDeviceId() == localUdid) {
            peerToken = static_cast<uint64_t>(item.GetAccessee().GetAccesseeTokenId());
            remoteTokenIds.insert(peerToken);
        }
    }
}

bool DeviceProfileConnector::CheckExtWhiteList(const std::string &pkgName)
{
    LOGI("start pkgName %{public}s.", pkgName.c_str());
    if (pkgName.empty()) {
        LOGE("bundleName empty.");
        return false;
    }
    for (uint32_t index = 0 ; index < AUTH_EXT_WHITE_LIST_NUM ; index++) {
        if (pkgName == g_extWhiteList[index]) {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::IsAllowAuthAlways(const std::string &localUdid, int32_t userId,
    const std::string &peerUdid, const std::string &pkgName, int64_t tokenId)
{
    auto acls = GetAclProfileByDeviceIdAndUserId(localUdid, userId, peerUdid);
    for (const auto &item : acls) {
        auto accesser = item.GetAccesser();
        auto accessee = item.GetAccessee();
        if (item.GetAuthenticationType() == ALLOW_AUTH_ALWAYS &&
            ((accesser.GetAccesserBundleName() == pkgName && accesser.GetAccesserTokenId() == tokenId) ||
            (accessee.GetAccesseeBundleName() == pkgName && accessee.GetAccesseeTokenId() == tokenId))) {
            return true;
        }
    }
    return false;
}

int32_t DeviceProfileConnector::GetAllAuthOnceAclInfos(
    std::unordered_set<AuthOnceAclInfo, AuthOnceAclInfoHash> &aclInfos)
{
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (auto &item : profiles) {
        if (item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        AuthOnceAclInfo aclInfo = { .peerUdid = item.GetTrustDeviceId() };
        auto accesser = item.GetAccesser();
        auto accessee = item.GetAccessee();
        if (accesser.GetAccesserDeviceId() == item.GetTrustDeviceId()) {
            aclInfo.peerUserId = accesser.GetAccesserUserId();
            aclInfo.localUserId = accessee.GetAccesseeUserId();
            aclInfos.insert(aclInfo);
        }
        if (accessee.GetAccesseeDeviceId() == item.GetTrustDeviceId()) {
            aclInfo.peerUserId = accessee.GetAccesseeUserId();
            aclInfo.localUserId = accesser.GetAccesserUserId();
            aclInfos.insert(aclInfo);
        }
    }
    return DM_OK;
}

void DeviceProfileConnector::DeleteDpInvalidAcl()
{
    std::vector<AccessControlProfile> profiles;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetAllAclIncludeLnnAcl(profiles);
    if (ret != DM_OK) {
        LOGE("DP failed, ret = %{public}d", ret);
        return;
    }
    for (auto item = profiles.begin(); item != profiles.end(); item++) {
        std::string acerAccountId = item->GetAccesser().GetAccesserAccountId();
        std::string aceeAccountId = item->GetAccessee().GetAccesseeAccountId();
        if (item->GetBindType() == DM_IDENTICAL_ACCOUNT && (acerAccountId == "ohosAnonymousUid" ||
            aceeAccountId == "ohosAnonymousUid")) {
            PrintProfile(*item);
            DistributedDeviceProfileClient::GetInstance().DeleteAccessControlProfile(item->GetAccessControlId());
        }
    }
}

DM_EXPORT void DeviceProfileConnector::GetAuthTypeByUdidHash(const std::string &udidHash, const std::string &pkgName,
    DMLocalServiceInfoAuthType &authType)
{
    authType = DMLocalServiceInfoAuthType::CANCEL;
    std::vector<AccessControlProfile> acls = GetAccessControlProfile();
    for (const auto &acl : acls) {
        if (Crypto::GetUdidHash(acl.GetTrustDeviceId()) != udidHash) {
            continue;
        }
        if (acl.GetBindType() == DM_IDENTICAL_ACCOUNT || acl.GetBindType() == DM_SHARE) {
            authType = DMLocalServiceInfoAuthType::TRUST_ALWAYS;
            return;
        }
        if ((acl.GetBindType() == DM_POINT_TO_POINT || acl.GetBindType() == DM_ACROSS_ACCOUNT) &&
            (acl.GetBindLevel() == USER || acl.GetAccesser().GetAccesserBundleName() == pkgName ||
            acl.GetAccessee().GetAccesseeBundleName() == pkgName)) {
            if (acl.GetAuthenticationType() == ALLOW_AUTH_ALWAYS) {
                authType = DMLocalServiceInfoAuthType::TRUST_ALWAYS;
                return;
            }
            authType = DMLocalServiceInfoAuthType::TRUST_ONETIME;
        }
    }
}

DM_EXPORT std::unordered_set<int32_t> DeviceProfileConnector::GetActiveAuthOncePeerUserId(const std::string &peerUdid,
    int32_t localUserId)
{
    std::unordered_set<int32_t> peerUserIds;
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(localUserId);
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid || item.GetStatus() != ACTIVE ||
            item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        auto accesser = item.GetAccesser();
        auto accessee = item.GetAccessee();
        if (accesser.GetAccesserDeviceId() == peerUdid && accessee.GetAccesseeUserId() == localUserId) {
            peerUserIds.insert(accesser.GetAccesserUserId());
        }
        if (accessee.GetAccesseeDeviceId() == peerUdid && accesser.GetAccesserUserId() == localUserId) {
            peerUserIds.insert(accessee.GetAccesseeUserId());
        }
    }
    return peerUserIds;
}

DM_EXPORT std::unordered_set<AuthOnceAclInfo, AuthOnceAclInfoHash> DeviceProfileConnector::GetAuthOnceAclInfos(
    const std::string &peerUdid)
{
    std::unordered_set<AuthOnceAclInfo, AuthOnceAclInfoHash> authOnceAclInfos;
    std::vector<AccessControlProfile> profiles = GetAllAccessControlProfile();
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid || item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        auto accesser = item.GetAccesser();
        auto accessee = item.GetAccessee();
        int32_t localUserId = 0;
        int32_t peerUserId = 0;
        if (accesser.GetAccesserDeviceId() == peerUdid) {
            localUserId = accessee.GetAccesseeUserId();
            peerUserId = accesser.GetAccesserUserId();
        }
        if (accessee.GetAccesseeDeviceId() == peerUdid) {
            localUserId = accesser.GetAccesserUserId();
            peerUserId = accessee.GetAccesseeUserId();
        }
        if (localUserId != 0 && peerUserId != 0) {
            authOnceAclInfos.insert({ .peerUdid = peerUdid, .peerUserId = peerUserId, .localUserId = localUserId });
        }
    }
    return authOnceAclInfos;
}

DM_EXPORT bool DeviceProfileConnector::AuthOnceAclIsActive(const std::string &peerUdid, int32_t peerUserId,
    int32_t localUserId)
{
    std::vector<AccessControlProfile> profiles = GetAccessControlProfileByUserId(localUserId);
    for (auto &item : profiles) {
        if (item.GetTrustDeviceId() != peerUdid || item.GetAuthenticationType() != ALLOW_AUTH_ONCE) {
            continue;
        }
        if (MatchAccesserByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item) ||
            MatchAccesseeByBothUserIdAndPeerUdid(peerUdid, peerUserId, localUserId, item)) {
            return item.GetStatus() == ACTIVE;
        }
    }
    return false;
}

DM_EXPORT int32_t DeviceProfileConnector::GetServiceInfoByUdidAndServiceId(const std::string &udid, int64_t serviceId,
    DistributedDeviceProfile::ServiceInfo &serviceInfo)
{
    LOGI("start");
    DistributedDeviceProfile::UserInfo userInfo;
    userInfo.udid = udid;
    std::vector<DistributedDeviceProfile::ServiceInfo> dpServiceInfos;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetServiceInfosByUserInfo(
        userInfo, dpServiceInfos);
    if (ret != DM_OK) {
        LOGE("GetServiceInfosByUdidAndServiceId failed, result: %{public}d", ret);
        if (ret == DP_NOT_FIND_DATA) {
            ret = ERR_DM_SERVICE_INFO_NOT_EXIST;
        }
        return ret;
    }
    for (auto &dpServiceInfo : dpServiceInfos) {
        if (dpServiceInfo.GetServiceId() == serviceId) {
            serviceInfo = dpServiceInfo;
            return DM_OK;
        }
    }
    LOGE("GetServiceInfosByUdidAndServiceId failed, udid not match");
    return ERR_DM_SERVICE_INFO_NOT_EXIST;
}

DM_EXPORT int32_t DeviceProfileConnector::GetServiceInfosByUdidAndUserId(const std::string &udid, int32_t userId,
    std::vector<DistributedDeviceProfile::ServiceInfo> &serviceInfos)
{
    LOGI("start");
    DistributedDeviceProfile::UserInfo userInfo;
    userInfo.udid = udid;
    userInfo.userId = userId;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetServiceInfosByUserInfo(
        userInfo, serviceInfos);
    if (ret != DM_OK) {
        LOGE("ret: %{public}d", ret);
        if (ret == DP_NOT_FIND_DATA) {
            ret = ERR_DM_SERVICE_INFO_NOT_EXIST;
        }
        return ret;
    }
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::PutServiceInfo(const DistributedDeviceProfile::ServiceInfo &serviceInfo)
{
    LOGI("start");
    int32_t ret = DistributedDeviceProfileClient::GetInstance().PutServiceInfo(serviceInfo);
    if (ret != DM_OK) {
        LOGE("result: %{public}d", ret);
        return ret;
    }
    LOGI("success");
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::DeleteServiceInfo(const DistributedDeviceProfile::ServiceInfo &serviceInfo)
{
    LOGI("start");
    DistributedDeviceProfile::UserInfo userInfo;
    userInfo.udid = serviceInfo.GetUdid();
    userInfo.userId = serviceInfo.GetUserId();
    userInfo.serviceId = serviceInfo.GetServiceId();
    int32_t ret = DistributedDeviceProfileClient::GetInstance().DeleteServiceInfo(userInfo);
    if (ret != DM_OK) {
        LOGE("result: %{public}d", ret);
        return ret;
    }
    LOGI("success");
    return DM_OK;
}

DM_EXPORT int32_t DeviceProfileConnector::GetServiceInfosByUdid(const std::string &udid,
    std::vector<DistributedDeviceProfile::ServiceInfo> &serviceInfos)
{
    DistributedDeviceProfile::UserInfo userInfo;
    userInfo.udid = udid;
    int32_t ret = DistributedDeviceProfileClient::GetInstance().GetServiceInfosByUserInfo(
        userInfo, serviceInfos);
    if (ret != DM_OK) {
        LOGE("result: %{public}d", ret);
        return ret;
    }
    LOGI("success");
    return DM_OK;
}

DM_EXPORT void DeviceProfileConnector::GetPeerTokenIdForServiceProxyUnbind(int32_t userId, uint64_t localTokenId,
    const std::string &peerUdid, int64_t serviceId, std::vector<uint64_t> &peerTokenId)
{
    char localUdid[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localUdid, DEVICE_UUID_LENGTH);
    std::vector<DistributedDeviceProfile::AccessControlProfile> profiles = GetAllAccessControlProfile();
    for (const auto& profile : profiles) {
        if (profile.GetAccesser().GetAccesserUserId() == userId &&
            static_cast<uint64_t>(profile.GetAccesser().GetAccesserTokenId()) == localTokenId &&
            profile.GetAccesser().GetAccesserDeviceId() == std::string(localUdid) &&
            profile.GetAccessee().GetAccesseeDeviceId() == peerUdid &&
            HasServiceId(profile, serviceId)) {
            peerTokenId.push_back(static_cast<uint64_t>(profile.GetAccessee().GetAccesseeTokenId()));
            break;
        }
        if (profile.GetAccessee().GetAccesseeUserId() == userId &&
            static_cast<uint64_t>(profile.GetAccessee().GetAccesseeTokenId()) == localTokenId &&
            profile.GetAccessee().GetAccesseeDeviceId() == std::string(localUdid) &&
            profile.GetAccesser().GetAccesserDeviceId() == peerUdid &&
            HasServiceId(profile, serviceId)) {
            peerTokenId.push_back(static_cast<uint64_t>(profile.GetAccesser().GetAccesserTokenId()));
            break;
        }
    }
}

bool DeviceProfileConnector::HasServiceId(const DistributedDeviceProfile::AccessControlProfile &profile,
    int64_t serviceId)
{
    LOGI("start.");
    std::string aceeExtraData = profile.GetAccessee().GetAccesseeExtraData();
    if (aceeExtraData.empty()) {
        LOGE("CheckAclByUdidAndTokenIdAndServiceId aceeExtraData is empty.");
        return false;
    }
    JsonObject aceeExtJson(aceeExtraData);
    if (aceeExtJson.IsDiscarded() || !IsArray(aceeExtJson, "serviceId")) {
        LOGE("serviceId is not exist.");
        return false;
    }

    JsonItemObject serviceIdItem = aceeExtJson["serviceId"];
    std::vector<int64_t> aceeServiceId;
    serviceIdItem.Get(aceeServiceId);
    auto it = std::find(aceeServiceId.begin(), aceeServiceId.end(), serviceId);
    if (it != aceeServiceId.end()) {
        return true;
    }
    return false;
}

int32_t DeviceProfileConnector::FillDmUserRemovedServiceInfoRemote(
    const DistributedDeviceProfile::AccessControlProfile &item,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    LOGI("start.");
    DmUserRemovedServiceInfo serviceInfo;
    serviceInfo.localTokenId = item.GetAccesser().GetAccesserTokenId();
    serviceInfo.localPkgName = item.GetAccesser().GetAccesserBundleName();
    serviceInfo.bindType = item.GetBindType();
    serviceInfo.peerUdid = item.GetAccessee().GetAccesseeDeviceId();
    serviceInfo.peerUserId = item.GetAccessee().GetAccesseeUserId();
    if (item.GetBindType() == DM_POINT_TO_POINT) {
        std::string aceeExtraData = item.GetAccessee().GetAccesseeExtraData();
        if (aceeExtraData.empty()) {
            LOGE("aceeExtraData is empty.");
            return ERR_DM_FAILED;
        }
        JsonObject aceeExtJson(aceeExtraData);
        if (aceeExtJson.IsDiscarded() || !IsArray(aceeExtJson, "serviceId")) {
            LOGE("serviceId is not exist.");
            return ERR_DM_FAILED;
        }
        JsonItemObject serviceIdItem = aceeExtJson["serviceId"];
        serviceIdItem.Get(serviceInfo.serviceIds);
    } else if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
        serviceInfo.serviceIds = {DM_DEFAULT_SERVICE_ID};
    }
    serviceInfos.push_back(serviceInfo);
    return DM_OK;
}

void DeviceProfileConnector::FillDmUserRemovedServiceInfoLocal(
    const DistributedDeviceProfile::AccessControlProfile &item,
    std::vector<DmUserRemovedServiceInfo> &serviceInfos)
{
    if (item.GetBindType() == DM_IDENTICAL_ACCOUNT) {
        DmUserRemovedServiceInfo serviceInfo;
        serviceInfo.localTokenId = item.GetAccesser().GetAccesserTokenId();
        serviceInfo.localPkgName = item.GetAccesser().GetAccesserBundleName();
        serviceInfo.bindType = item.GetBindType();
        serviceInfo.peerUdid = item.GetAccessee().GetAccesseeDeviceId();
        serviceInfo.peerUserId = item.GetAccessee().GetAccesseeUserId();
        serviceInfo.serviceIds = {DM_DEFAULT_SERVICE_ID};
        serviceInfos.push_back(serviceInfo);
    }
}

IDeviceProfileConnector *CreateDpConnectorInstance()
{
    return &DeviceProfileConnector::GetInstance();
}

void DeviceProfileConnector::HandleDistributedAccountLogin(const std::string &localUdid, int32_t userId,
    const std::string &accountId)
{
    LOGI("HandleDistributedAccountLogin: localUdid %{public}s, userId %{public}d, accountId %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str());
    UpdateAclStatusByAccountId(localUdid, userId, accountId, ACTIVE);
}

void DeviceProfileConnector::HandleDistributedAccountUnbound(const std::string &localUdid, int32_t userId,
    const std::string &accountId)
{
    LOGI("HandleDistributedAccountUnbound: localUdid %{public}s, userId %{public}d, accountId %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str());
    DeleteAclByAccountId(localUdid, userId, accountId);
}

void DeviceProfileConnector::HandleDistributedAccountLogout(const std::string &localUdid, int32_t userId,
    const std::string &accountId)
{
    LOGI("HandleDistributedAccountLogout: localUdid %{public}s, userId %{public}d, accountId %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str());
    UpdateAclStatusByAccountId(localUdid, userId, accountId, INACTIVE);
}

void DeviceProfileConnector::HandleDistributedAccountLogout(const std::string &localUdid, int32_t userId,
    const std::string &accountId, const std::string &peerUdid)
{
    LOGI("HandleDistributedAccountLogout: localUdid %{public}s, userId %{public}d, accountId %{public}s,"
        "peerUdid %{public}s", GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str(),
        GetAnonyString(peerUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountId(profile, localUdid, userId, accountId, peerUdid)) {
            AccessControlProfile updateProfile = profile;
            updateProfile.SetStatus(INACTIVE);
            int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(updateProfile);
            if (ret != DM_OK) {
                LOGE("UpdateAccessControlProfile failed for accountId %{public}s, peerUdid %{public}s, ret %{public}d",
                    GetAnonyString(accountId).c_str(), GetAnonyString(peerUdid).c_str(), ret);
            }
        }
    }
}

void DeviceProfileConnector::HandleSubProfileSwitched(const std::string &localUdid, int32_t userId,
    int32_t currentSubProfileId, int32_t previousSubProfileId)
{
    LOGI("localUdid %{public}s, userId %{public}d, currentSubProfileId %{public}d, "
        "previousSubProfileId %{public}d", GetAnonyString(localUdid).c_str(), userId,
        currentSubProfileId, previousSubProfileId);
    std::string previousAccountId = MultipleUserConnector::GetAccountIdBySubProfileId(userId, previousSubProfileId);
    std::string currentAccountId = MultipleUserConnector::GetAccountIdBySubProfileId(userId, currentSubProfileId);
    UpdateAclStatusByAccountId(localUdid, userId, previousAccountId, INACTIVE);
    UpdateAclStatusByAccountId(localUdid, userId, currentAccountId, ACTIVE);
}

bool DeviceProfileConnector::IsAccountInForeground(int32_t userId, const std::string &accountIdHash,
    const std::vector<ForegroundAccountInfo> &foregroundAccounts)
{
    for (const auto &account : foregroundAccounts) {
        if (account.userId == userId && account.accountId == accountIdHash) {
            return true;
        }
    }
    return false;
}

bool DeviceProfileConnector::IsAccountInForegroundByUserId(int32_t userId,
    const std::vector<ForegroundAccountInfo> &foregroundAccounts)
{
    for (const auto &account : foregroundAccounts) {
        if (account.userId == userId) {
            return true;
        }
    }
    return false;
}

int32_t DeviceProfileConnector::GetDeviceTypeFromExtraData(const std::string &extraData)
{
    if (extraData.empty()) {
        return DEVICE_TYPE_UNKNOWN;
    }
    JsonObject extJson(extraData);
    if (!extJson.IsDiscarded() && extJson["deviceType"].IsNumber()) {
        return extJson["deviceType"].Get<int32_t>();
    }
    return DEVICE_TYPE_UNKNOWN;
}

int32_t DeviceProfileConnector::CalculateProfileTargetStatus(const AccessControlProfile &profile,
    const std::string &localUdid, const std::string &peerUdid,
    const std::vector<ForegroundAccountInfo> &localForegroundAccounts,
    const std::vector<ForegroundAccountInfo> &peerForegroundAccounts)
{
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    if ((accesserUdid != localUdid || accesseeUdid != peerUdid) &&
        (accesserUdid != peerUdid || accesseeUdid != localUdid)) {
        return INVALID_PROFILE_STATUS;
    }

    char accesserAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    char accesseeAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    if (Crypto::GetAccountIdHash7(profile.GetAccesser().GetAccesserAccountId(),
        reinterpret_cast<uint8_t *>(accesserAccountIdHash)) != DM_OK ||
        Crypto::GetAccountIdHash7(profile.GetAccessee().GetAccesseeAccountId(),
        reinterpret_cast<uint8_t *>(accesseeAccountIdHash)) != DM_OK) {
        return INVALID_PROFILE_STATUS;
    }

    bool localNeedCheckAccountId = true;
    bool peerNeedCheckAccountId = true;
    bool isP2P = (profile.GetBindType() == DM_POINT_TO_POINT || profile.GetBindType() == DM_ACROSS_ACCOUNT);
    if (isP2P) {
        int32_t accesserDeviceType = GetDeviceTypeFromExtraData(profile.GetAccesser().GetAccesserExtraData());
        int32_t accesseeDeviceType = GetDeviceTypeFromExtraData(profile.GetAccessee().GetAccesseeExtraData());
        localNeedCheckAccountId = (accesserUdid == localUdid) ?
            (accesserDeviceType == DEVICE_TYPE_CAR) : (accesseeDeviceType == DEVICE_TYPE_CAR);
        peerNeedCheckAccountId = (accesserUdid == localUdid) ?
            (accesseeDeviceType == DEVICE_TYPE_CAR) : (accesserDeviceType == DEVICE_TYPE_CAR);
    }

    int32_t accesserUserId = profile.GetAccesser().GetAccesserUserId();
    int32_t accesseeUserId = profile.GetAccessee().GetAccesseeUserId();
    auto localCheck = [&](int32_t userId, const std::string &accountIdHash) {
        return localNeedCheckAccountId ? IsAccountInForeground(userId, accountIdHash, localForegroundAccounts) :
            IsAccountInForegroundByUserId(userId, localForegroundAccounts);
    };
    auto peerCheck = [&](int32_t userId, const std::string &accountIdHash) {
        return peerNeedCheckAccountId ? IsAccountInForeground(userId, accountIdHash, peerForegroundAccounts) :
            IsAccountInForegroundByUserId(userId, peerForegroundAccounts);
    };

    bool localInForeground = (accesserUdid == localUdid) ?
        localCheck(accesserUserId, accesserAccountIdHash) : localCheck(accesseeUserId, accesseeAccountIdHash);
    bool peerInForeground = (accesserUdid == localUdid) ?
        peerCheck(accesseeUserId, accesseeAccountIdHash) : peerCheck(accesserUserId, accesserAccountIdHash);

    return (localInForeground && peerInForeground) ? ACTIVE : INACTIVE;
}

int32_t DeviceProfileConnector::UpdateAclByDualForegroundAccountHash(const std::string &localUdid,
    const std::string &peerUdid, const std::vector<ForegroundAccountInfo> &localForegroundAccounts,
    const std::vector<ForegroundAccountInfo> &peerForegroundAccounts)
{
    LOGI("localUdid %{public}s, peerUdid %{public}s, localAccounts %{public}zu, peerAccounts %{public}zu",
        GetAnonyString(localUdid).c_str(), GetAnonyString(peerUdid).c_str(),
        localForegroundAccounts.size(), peerForegroundAccounts.size());
    
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    std::vector<AccessControlProfile> inactiveProfiles;
    std::vector<AccessControlProfile> activeProfiles;
    
    for (const auto &profile : profiles) {
        int32_t targetStatus = CalculateProfileTargetStatus(profile, localUdid, peerUdid,
            localForegroundAccounts, peerForegroundAccounts);
        if (targetStatus < 0 || profile.GetStatus() == targetStatus) {
            continue;
        }
        
        AccessControlProfile updateProfile = profile;
        updateProfile.SetStatus(targetStatus);
        if (targetStatus == INACTIVE) {
            inactiveProfiles.push_back(updateProfile);
        } else {
            activeProfiles.push_back(updateProfile);
        }
    }
    
    for (const auto &profile : inactiveProfiles) {
        int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
        if (ret != DM_OK) {
            LOGE("Update inactive profile failed, ret %{public}d", ret);
            return ret;
        }
    }
    
    for (const auto &profile : activeProfiles) {
        int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(profile);
        if (ret != DM_OK) {
            LOGE("Update active profile failed, ret %{public}d", ret);
            return ret;
        }
    }
    
    return DM_OK;
}

bool DeviceProfileConnector::CheckAclMatchByAccountId(const AccessControlProfile &profile,
    const std::string &localUdid, int32_t userId, const std::string &accountId)
{
    return CheckAclMatchByAccountId(profile, localUdid, userId, accountId, "");
}

bool DeviceProfileConnector::CheckAclMatchByAccountId(const AccessControlProfile &profile,
    const std::string &localUdid, int32_t userId, const std::string &accountId, const std::string &peerUdid)
{
    return CheckAclMatchAccesser(profile, localUdid, userId, accountId, peerUdid) ||
        CheckAclMatchAccessee(profile, localUdid, userId, accountId, peerUdid);
}

bool DeviceProfileConnector::CheckAclMatchAccesser(const AccessControlProfile &profile,
    const std::string &localUdid, int32_t userId, const std::string &accountId, const std::string &peerUdid)
{
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    int32_t accesserUserId = profile.GetAccesser().GetAccesserUserId();
    std::string accesserAccountId = profile.GetAccesser().GetAccesserAccountId();
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    
    if (accesserUdid != localUdid || accesserUserId != userId) {
        return false;
    }
    if (accesserAccountId != accountId) {
        return false;
    }
    if (!peerUdid.empty() && accesseeUdid != peerUdid) {
        return false;
    }
    return true;
}

bool DeviceProfileConnector::CheckAclMatchAccessee(const AccessControlProfile &profile,
    const std::string &localUdid, int32_t userId, const std::string &accountId, const std::string &peerUdid)
{
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t accesseeUserId = profile.GetAccessee().GetAccesseeUserId();
    std::string accesseeAccountId = profile.GetAccessee().GetAccesseeAccountId();
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    
    if (accesseeUdid != localUdid || accesseeUserId != userId) {
        return false;
    }
    if (accesseeAccountId != accountId) {
        return false;
    }
    if (!peerUdid.empty() && accesserUdid != peerUdid) {
        return false;
    }
    return true;
}

bool DeviceProfileConnector::CheckAclMatchByAccountIdHash(const AccessControlProfile &profile,
    const std::string &peerUdid, int32_t userId, const std::string &accountIdHash)
{
    return CheckAclMatchAccesserByAccountIdHash(profile, peerUdid, userId, accountIdHash) ||
        CheckAclMatchAccesseeByAccountIdHash(profile, peerUdid, userId, accountIdHash);
}

bool DeviceProfileConnector::CheckAclMatchAccesserByAccountIdHash(const AccessControlProfile &profile,
    const std::string &peerUdid, int32_t userId, const std::string &accountIdHash)
{
    std::string accesserUdid = profile.GetAccesser().GetAccesserDeviceId();
    int32_t accesserUserId = profile.GetAccesser().GetAccesserUserId();
    std::string accesserAccountId = profile.GetAccesser().GetAccesserAccountId();
    char accesserAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    if (Crypto::GetAccountIdHash7(accesserAccountId, reinterpret_cast<uint8_t *>(accesserAccountIdHash)) != DM_OK) {
        return false;
    }
    return (accesserUdid == peerUdid && accesserUserId == userId &&
        std::string(accesserAccountIdHash) == accountIdHash);
}

bool DeviceProfileConnector::CheckAclMatchAccesseeByAccountIdHash(const AccessControlProfile &profile,
    const std::string &peerUdid, int32_t userId, const std::string &accountIdHash)
{
    std::string accesseeUdid = profile.GetAccessee().GetAccesseeDeviceId();
    int32_t accesseeUserId = profile.GetAccessee().GetAccesseeUserId();
    std::string accesseeAccountId = profile.GetAccessee().GetAccesseeAccountId();
    char accesseeAccountIdHash[DM_MAX_DEVICE_ID_LEN] = {0};
    if (Crypto::GetAccountIdHash7(accesseeAccountId, reinterpret_cast<uint8_t *>(accesseeAccountIdHash)) != DM_OK) {
        return false;
    }
    return (accesseeUdid == peerUdid && accesseeUserId == userId &&
        std::string(accesseeAccountIdHash) == accountIdHash);
}

std::vector<AccessControlProfile> DeviceProfileConnector::GetAclByAccountId(
    const std::string &localUdid, int32_t userId, const std::string &accountId)
{
    std::vector<AccessControlProfile> result;
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountId(profile, localUdid, userId, accountId)) {
            result.push_back(profile);
        }
    }
    LOGI("GetAclByAccountId: found %{public}zu ACLs for accountId %{public}s",
        result.size(), GetAnonyString(accountId).c_str());
    return result;
}

int32_t DeviceProfileConnector::UpdateAclStatusByAccountId(const std::string &localUdid, int32_t userId,
    const std::string &accountId, int32_t newStatus)
{
    LOGI("localUdid %{public}s, userId %{public}d, accountId %{public}s, newStatus %{public}d",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str(), newStatus);
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    int32_t updateCount = 0;
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountId(profile, localUdid, userId, accountId) && profile.GetStatus() != newStatus) {
            AccessControlProfile updateProfile = profile;
            updateProfile.SetStatus(newStatus);
            int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(updateProfile);
            if (ret == DM_OK) {
                updateCount++;
            } else {
                LOGE("UpdateAccessControlProfile failed, ret %{public}d", ret);
            }
        }
    }
    LOGI("Updated %{public}d ACLs", updateCount);
    return DM_OK;
}

int32_t DeviceProfileConnector::UpdateAclStatusByAccountIdHash(const std::string &localUdid, int32_t userId,
    const std::string &accountIdHash, int32_t newStatus, const std::string &peerUdid)
{
    LOGI("localUdid %{public}s, userId %{public}d, accountIdHash %{public}s, newStatus %{public}d, peerUdid %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountIdHash).c_str(), newStatus,
        GetAnonyString(peerUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    int32_t updateCount = 0;
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountIdHash(profile, peerUdid, userId, accountIdHash) &&
            profile.GetStatus() != newStatus) {
            AccessControlProfile updateProfile = profile;
            updateProfile.SetStatus(newStatus);
            int32_t ret = DistributedDeviceProfileClient::GetInstance().UpdateAccessControlProfile(updateProfile);
            if (ret == DM_OK) {
                updateCount++;
            } else {
                LOGE("UpdateAccessControlProfile failed (accesser), ret %{public}d", ret);
            }
        }
    }
    LOGI("Updated %{public}d ACLs by accountIdHash", updateCount);
    return DM_OK;
}

int32_t DeviceProfileConnector::DeleteAclByAccountId(const std::string &localUdid, int32_t userId,
    const std::string &accountId)
{
    return DeleteAclByAccountId(localUdid, userId, accountId, "");
}

int32_t DeviceProfileConnector::DeleteAclByAccountId(const std::string &localUdid, int32_t userId,
    const std::string &accountId, const std::string &peerUdid)
{
    LOGI("localUdid %{public}s, userId %{public}d, accountId %{public}s, peerUdid %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountId).c_str(),
        GetAnonyString(peerUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    int32_t deleteCount = 0;
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountId(profile, localUdid, userId, accountId, peerUdid)) {
            DeleteAccessControlById(profile.GetAccessControlId());
            deleteCount++;
        }
    }
    LOGI("Deleted %{public}d ACLs", deleteCount);
    return DM_OK;
}

int32_t DeviceProfileConnector::DeleteAclByAccountIdHash(const std::string &localUdid, int32_t userId,
    const std::string &accountIdHash, const std::string &peerUdid)
{
    LOGI("localUdid %{public}s, userId %{public}d, accountIdHash %{public}s, peerUdid %{public}s",
        GetAnonyString(localUdid).c_str(), userId, GetAnonyString(accountIdHash).c_str(),
        GetAnonyString(peerUdid).c_str());
    std::vector<AccessControlProfile> profiles = GetAllAclIncludeLnnAcl();
    int32_t deleteCount = 0;
    for (const auto &profile : profiles) {
        if (CheckAclMatchByAccountIdHash(profile, peerUdid, userId, accountIdHash)) {
            DeleteAccessControlById(profile.GetAccessControlId());
            deleteCount++;
        }
    }
    LOGI("Deleted %{public}d ACLs by accountIdHash", deleteCount);
    return DM_OK;
}
} // namespace DistributedHardware
} // namespace OHOS