/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <memory>

#include "app_manager.h"
#include "business_event.h"
#include "distributed_device_profile_client.h"
#include "softbus_common.h"
#include "system_ability_definition.h"
#include "iservice_registry.h"
#include "parameter.h"
#include "deviceprofile_connector.h"
#include "multiple_user_connector.h"

#include "auth_manager.h"
#include "dm_constants.h"
#include "dm_crypto.h"
#include "dm_random.h"
#include "dm_log.h"
#include "dm_timer.h"
#include "dm_radar_helper.h"
#include "dm_device_info.h"
#include "dm_anonymous.h"
#include "dm_auth_state_machine.h"
#include "dm_auth_context.h"
#include "dm_auth_message_processor.h"
#include "dm_auth_state.h"
#include "json_object.h"

#ifdef SUPPORT_MSDP
#include "spatial_awareness_mgr_client.h"
#endif

namespace OHOS {
namespace DistributedHardware {
namespace {

constexpr int32_t MIN_PIN_CODE = 100000;
constexpr int32_t MAX_PIN_CODE = 999999;
constexpr int32_t DM_ULTRASONIC_FORWARD = 0;
constexpr int32_t DM_ULTRASONIC_REVERSE = 1;
constexpr int32_t INVALID_USERID = -1;
constexpr int32_t MAIN_SCREEN_DISPLAYID = 0;
const char* IS_NEED_JOIN_LNN = "IsNeedJoinLnn";
constexpr const char* NEED_JOIN_LNN = "0";
constexpr const char* NO_NEED_JOIN_LNN = "1";
const char* DM_REJECT_KEY = "business_id_cast+_reject_event";
const char* DM_AUTH_DIALOG_REJECT = "is_auth_dialog_reject";
const char* DM_TIMESTAMP = "timestamp";
const char* TAG_NCM_BIND_TARGET = "ncm_bind_target";
constexpr const char* TAG_NCM_BIND_TARGET_TRUE = "1";
int32_t GetCloseSessionDelaySeconds(std::string &delaySecondsStr)
{
    if (!IsNumberString(delaySecondsStr)) {
        LOGE("Invalid parameter, param is not number.");
        return 0;
    }
    const int32_t closeSessionDelaySecondsMax = 10;
    int32_t delaySeconds = std::atoi(delaySecondsStr.c_str());
    if (delaySeconds < 0 || delaySeconds > closeSessionDelaySecondsMax) {
        LOGE("Invalid parameter, param out of range.");
        return 0;
    }
    return delaySeconds;
}
//LCOV_EXCL_START
std::string GetBundleLabel(const std::string &bundleName)
{
    auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (samgr == nullptr) {
        LOGE("Get ability manager failed");
        return bundleName;
    }
 
    sptr<IRemoteObject> object = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
    if (object == nullptr) {
        LOGE("object is NULL.");
        return bundleName;
    }
 
    sptr<OHOS::AppExecFwk::IBundleMgr> bms = iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
    if (bms == nullptr) {
        LOGE("bundle manager service is NULL.");
        return bundleName;
    }
 
    auto bundleResourceProxy = bms->GetBundleResourceProxy();
    if (bundleResourceProxy == nullptr) {
        LOGE("GetBundleResourceProxy fail");
        return bundleName;
    }
    AppExecFwk::BundleResourceInfo resourceInfo;
    auto result = bundleResourceProxy->GetBundleResourceInfo(bundleName,
        static_cast<uint32_t>(OHOS::AppExecFwk::ResourceFlag::GET_RESOURCE_INFO_ALL), resourceInfo);
    if (result != ERR_OK) {
        LOGE("GetBundleResourceInfo failed");
        return bundleName;
    }
    LOGI("bundle resource label is %{public}s ", (resourceInfo.label).c_str());
    return resourceInfo.label;
}
//LCOV_EXCL_STOP
std::string ParseExtraFromMap(const std::map<std::string, std::string> &bindParam)
{
    auto iter = bindParam.find(PARAM_KEY_BIND_EXTRA_DATA);
    if (iter != bindParam.end()) {
        return iter->second;
    }
    return ConvertMapToJsonString(bindParam);
}

}  // namespace

AuthManager::AuthManager(std::shared_ptr<SoftbusConnector> softbusConnector,
                         std::shared_ptr<HiChainConnector> hiChainConnector,
                         std::shared_ptr<IDeviceManagerServiceListener> listener,
                         std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)
{
    LOGI("constructor");
    context_ = std::make_shared<DmAuthContext>();
    context_->softbusConnector = softbusConnector;
    context_->listener = listener;
    context_->hiChainConnector = hiChainConnector;
    context_->hiChainAuthConnector = hiChainAuthConnector;
    context_->authUiStateMgr = std::make_shared<AuthUiStateManager>(context_->listener);
    context_->authenticationMap[AUTH_TYPE_PIN] = nullptr;
    context_->authenticationMap[AUTH_TYPE_IMPORT_AUTH_CODE] = nullptr;
    context_->authenticationMap[AUTH_TYPE_PIN_ULTRASONIC] = nullptr;
    context_->authenticationMap[AUTH_TYPE_NFC] = nullptr;
    context_->authenticationMap[AUTH_TYPE_CRE] = nullptr;
    context_->accesser.dmVersion = DM_CURRENT_VERSION;
    context_->accessee.dmVersion = DM_CURRENT_VERSION;
    context_->timer = std::make_shared<DmTimer>();
    context_->authMessageProcessor = std::make_shared<DmAuthMessageProcessor>();
    context_->businessId = "";
}

AuthManager::~AuthManager()
{
    if (context_ != nullptr) {
        context_->successFinished = true;
        if (context_->authStateMachine != nullptr) {
            context_->authStateMachine->Stop();  // Stop statemMachine thread
        }
        if (context_->timer != nullptr) {
            context_->timer->DeleteAll();
        }
        LOGI("AuthManager context variables destroy successful.");
    }
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        bindParam_.clear();
    }
    LOGI("destructor");
}

void AuthManager::RegisterCleanNotifyCallback(CleanNotifyCallback cleanNotifyCallback)
{
    CHECK_NULL_VOID(context_);
    context_->cleanNotifyCallback = cleanNotifyCallback;
    return;
}

void AuthManager::RegisterStopTimerAndDelDpCallback(StopTimerAndDelDpCallback stopTimerAndDelDpCallback)
{
    context_->stopTimerAndDelDpCallback = stopTimerAndDelDpCallback;
}

void AuthManager::SetAuthContext(std::shared_ptr<DmAuthContext> context)
{
    this->context_ = context;
}

std::shared_ptr<DmAuthContext> AuthManager::GetAuthContext()
{
    return this->context_;
}

std::string AuthManager::GeneratePincode()
{
    LOGI("start");
    int32_t pinCode = GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE);
    CHECK_NULL_RETURN(context_, "");
    context_->pinCode = std::to_string(pinCode);
    return context_->pinCode;
}

int32_t AuthManager::RegisterUiStateCallback(const std::string pkgName)
{
    LOGI("start");
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    if (context_->authUiStateMgr == nullptr) {
        LOGE("context_->authUiStateMgr is null.");
        return ERR_DM_FAILED;
    }
    context_->authUiStateMgr->RegisterUiStateCallback(pkgName);
    return DM_OK;
}

int32_t AuthManager::UnRegisterUiStateCallback(const std::string pkgName)
{
    LOGI("start");
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    if (context_->authUiStateMgr == nullptr) {
        LOGE("context_->authUiStateMgr is null.");
        return ERR_DM_FAILED;
    }
    context_->authUiStateMgr->UnRegisterUiStateCallback(pkgName);
    return DM_OK;
}

int32_t AuthManager::UnAuthenticateDevice(const std::string &pkgName, const std::string &udid, int32_t bindLevel)
{
    LOGI("start");
    return ERR_DM_FAILED;
}

int32_t AuthManager::ImportAuthCode(const std::string &pkgName, const std::string &authCode)
{
    if (authCode.empty() || pkgName.empty()) {
        LOGE("authCode or pkgName is empty");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    context_->importAuthCode = authCode;
    context_->importPkgName = pkgName;
    context_->pinCode = authCode;
    LOGI("ok");
    return DM_OK;
}

int32_t AuthManager::UnBindDevice(const std::string &pkgName, const std::string &udid,
    int32_t bindLevel, const std::string &extra)
{
    LOGI("start");
    return ERR_DM_FAILED;
}

int32_t AuthManager::StopAuthenticateDevice(const std::string &pkgName)
{
    (void)pkgName;
    LOGI("start");
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    context_->connDelayCloseTime = 0;
    context_->reason = STOP_BIND;
    CHECK_NULL_RETURN(context_->authStateMachine, ERR_DM_POINT_NULL);
    if (context_->authStateMachine->IsWaitEvent()) {
        context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
        return DM_OK;
    }

    if (context_->direction == DM_AUTH_SOURCE) {
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcFinishState>());
    } else {
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSinkFinishState>());
    }
    context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
    return DM_OK;
}

void AuthManager::NotifyRemoteFailed(int32_t sessionId, int32_t reason, uint64_t logicalSessionId)
{
    CHECK_NULL_VOID(context_);
    if (context_->direction == DmAuthDirection::DM_AUTH_SINK) {
        context_->reply = reason;
        context_->reason = reason;
        context_->sessionId = sessionId;
        context_->logicalSessionId = logicalSessionId;
        CHECK_NULL_VOID(context_->authMessageProcessor);
        context_->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_AUTH_RESP_FINISH, context_);
    }
}

void AuthManager::OnScreenLocked()
{
    LOGI("start");
    CHECK_NULL_VOID(context_);
    if (DmAuthState::IsImportAuthCodeCompatibility(context_->authType)) {
        LOGI("authtype is: %{public}d, no need stop bind.", context_->authType);
        return;
    }
    context_->reason = ERR_DM_BIND_USER_CANCEL;
    context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
}

void AuthManager::HandleDeviceNotTrust(const std::string &udid)
{
    LOGI("start");
}

int32_t AuthManager::RegisterAuthenticationType(int32_t authenticationType)
{
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    context_->confirmOperation = static_cast<UiAction>(authenticationType);
    return DM_OK;
}

int32_t AuthManager::GetReason()
{
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    return context_->reason;
}

// Save the key
void AuthSrcManager::AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen)
{
    LOGI("start. keyLen: %{public}u", sessionKeyLen);
    if (context_ == nullptr || context_->authMessageProcessor == nullptr || context_->authStateMachine == nullptr) {
        LOGE("auth context not initial.");
        return;
    }
    if (requestId != context_->requestId) {
        LOGE("requestId %{public}" PRId64 "is error.", requestId);
        return;
    }
    int32_t ret = context_->authMessageProcessor->SaveSessionKey(sessionKey, sessionKeyLen);
    if (ret != DM_OK) {
        LOGE("save session key error, ret: %{public}d", ret);
    }

    context_->authStateMachine->NotifyEventFinish(ON_SESSION_KEY_RETURNED);
    LOGI("leave.");
}

char *AuthSrcManager::AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams)
{
    LOGI("start");
    return nullptr;
}

void AuthManager::SetAuthType(int32_t authType)
{
    CHECK_NULL_VOID(context_);
    context_->authType = (DmAuthType)authType;
}

bool AuthManager::IsAuthTypeSupported(const int32_t &authType)
{
    CHECK_NULL_RETURN(context_, false);
    if (context_->authenticationMap.find(authType) == context_->authenticationMap.end()) {
        LOGE("authType is not supported.");
        return false;
    }
    return true;
}

bool AuthManager::IsAuthCodeReady(const std::string &pkgName)
{
    CHECK_NULL_RETURN(context_, false);
    if (context_->importAuthCode.empty() || context_->importPkgName.empty()) {
        LOGE("auth code not ready with authCode %{public}s and pkgName %{public}s.",
            GetAnonyString(context_->importAuthCode).c_str(), context_->importPkgName.c_str());
        return false;
    }
    if (pkgName != context_->importPkgName) {
        LOGE("pkgName %{public}s not supported with import pkgName %{public}s.",
            pkgName.c_str(), context_->importPkgName.c_str());
        return false;
    }
    return true;
}

int32_t AuthManager::CheckAuthParamVaild(const std::string &pkgName, int32_t authType,
    const std::string &deviceId, const std::string &extra)
{
    LOGI("start.");
    if (authType < DM_AUTH_TYPE_MIN || authType > DM_AUTH_TYPE_MAX) {
        LOGE("authType is illegal.");
        return ERR_DM_AUTH_FAILED;
    }
    if (pkgName.empty() || deviceId.empty()) {
        LOGE("pkgName is %{public}s, deviceId is %{public}s, extra is"
            "%{public}s.", pkgName.c_str(), GetAnonyString(deviceId).c_str(), extra.c_str());
        return ERR_DM_INPUT_PARA_INVALID;
    }
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    if (context_->listener == nullptr || context_->authUiStateMgr == nullptr) {
        LOGE("listener or authUiStateMgr is nullptr.");
        return ERR_DM_INPUT_PARA_INVALID;
    }

    if (!IsAuthTypeSupported(authType)) {
        LOGE("authType %{public}d not support.", authType);
        context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "",
            STATUS_DM_AUTH_DEFAULT,
            ERR_DM_UNSUPPORTED_AUTH_TYPE);
        context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId,
            ERR_DM_UNSUPPORTED_AUTH_TYPE, STATUS_DM_AUTH_DEFAULT, "");
        return ERR_DM_UNSUPPORTED_AUTH_TYPE;
    }
    JsonObject jsonObject(extra);
    CHECK_NULL_RETURN(context_->softbusConnector, ERR_DM_POINT_NULL);
    if ((jsonObject.IsDiscarded() || !IsString(jsonObject, PARAM_KEY_CONN_SESSIONTYPE) ||
        jsonObject[PARAM_KEY_CONN_SESSIONTYPE].Get<std::string>() != CONN_SESSION_TYPE_HML) &&
        !context_->softbusConnector->HaveDeviceInMap(deviceId)) {
        LOGE("the discoveryDeviceInfoMap_ not have this device.");
        context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "",
            STATUS_DM_AUTH_DEFAULT, ERR_DM_INPUT_PARA_INVALID);
        context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId,
            ERR_DM_INPUT_PARA_INVALID, STATUS_DM_AUTH_DEFAULT, "");
        return ERR_DM_INPUT_PARA_INVALID;
    }

    if (DmAuthState::IsImportAuthCodeCompatibility(static_cast<DmAuthType>(authType)) &&
        (!IsAuthCodeReady(pkgName))) {
        LOGE("Auth code not exist.");
        context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId, "",
            STATUS_DM_AUTH_DEFAULT, ERR_DM_INPUT_PARA_INVALID);
        context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId,
            ERR_DM_INPUT_PARA_INVALID, STATUS_DM_AUTH_DEFAULT, "");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    return DM_OK;
}

void AuthManager::ParseHmlInfoInJsonObject(const JsonObject &jsonObject)
{
    CHECK_NULL_VOID(context_);
    if (jsonObject[PARAM_KEY_CONN_SESSIONTYPE].IsString()) {
        context_->connSessionType = jsonObject[PARAM_KEY_CONN_SESSIONTYPE].Get<std::string>();
        LOGI("connSessionType %{public}s", context_->connSessionType.c_str());
    }
    GetDelayCloseConnTime(jsonObject);
    if (context_->connSessionType != CONN_SESSION_TYPE_HML) {
        return;
    }
    if (jsonObject[PARAM_KEY_HML_ENABLE_160M].IsBoolean()) {
        context_->hmlEnable160M = jsonObject[PARAM_KEY_HML_ENABLE_160M].Get<bool>();
        LOGI("hmlEnable160M %{public}d", context_->hmlEnable160M);
    }
    if (jsonObject[PARAM_KEY_HML_ACTIONID].IsString()) {
        std::string actionIdStr = jsonObject[PARAM_KEY_HML_ACTIONID].Get<std::string>();
        if (IsNumberString(actionIdStr)) {
            context_->hmlActionId = std::atoi(actionIdStr.c_str());
        }
        if (context_->hmlActionId <= 0) {
            context_->hmlActionId = 0;
        }
        LOGI("hmlActionId %{public}d", context_->hmlActionId);
    }

    return;
}

std::string AuthManager::GetBundleName(const JsonObject &jsonObject)
{
    if (!jsonObject.IsDiscarded() && jsonObject[BUNDLE_NAME_KEY].IsString()) {
        return jsonObject[BUNDLE_NAME_KEY].Get<std::string>();
    }
    bool isSystemSA = false;
    std::string bundleName;
    AppManager::GetInstance().GetCallerName(isSystemSA, bundleName);
    return bundleName;
}
void AuthManager::ParseJsonObject(const JsonObject &jsonObject)
{
    CHECK_NULL_VOID(context_);
    if (IsString(jsonObject, DM_BUSINESS_ID)) {
        context_->businessId = jsonObject[DM_BUSINESS_ID].Get<std::string>();
    }
    if (!MultipleUserConnector::CheckMDMControl()) {
        if (jsonObject[APP_OPERATION_KEY].IsString()) {
            context_->appOperation = jsonObject[APP_OPERATION_KEY].Get<std::string>();
        }
        if (jsonObject[CUSTOM_DESCRIPTION_KEY].IsString()) {
            context_->customData = jsonObject[CUSTOM_DESCRIPTION_KEY].Get<std::string>();
        }
        if (jsonObject[TAG_APP_THUMBNAIL2].IsString()) {
            context_->appThumbnail = jsonObject[TAG_APP_THUMBNAIL2].Get<std::string>();
        }
    }
    ParseAccessJsonObject(jsonObject);
    if (jsonObject[TAG_IS_NEED_AUTHENTICATE].IsString()) {
        context_->isNeedAuthenticate = std::atoi(jsonObject[TAG_IS_NEED_AUTHENTICATE].Get<std::string>().c_str());
        LOGI("isNeedAuthenticate: %{public}d.", context_->isNeedAuthenticate);
    }
    if (context_->authType == AUTH_TYPE_PIN_ULTRASONIC) {
        ParseUltrasonicSide(jsonObject);
    }
    if (context_->accesser.bundleName == BUNDLE_NAME_COLLABORATION_FWK &&
        IsString(jsonObject, TAG_NCM_BIND_TARGET)) {
        std::string ncmStr = jsonObject[TAG_NCM_BIND_TARGET].Get<std::string>();
        context_->ncmBindTarget = ncmStr == TAG_NCM_BIND_TARGET_TRUE ? true : false;
    }
    ParseHmlInfoInJsonObject(jsonObject);
    if (context_->isServiceBind) {
        ParseServiceJsonObject(jsonObject);
        return;
    }
    ParseProxyJsonObject(jsonObject);
    return;
}

void AuthManager::ParseAccessJsonObject(const JsonObject &jsonObject)
{
    CHECK_NULL_VOID(context_);
    context_->accessee.bundleName = context_->accesser.bundleName;
    if (jsonObject[TAG_PEER_BUNDLE_NAME].IsString() && !jsonObject[TAG_PEER_BUNDLE_NAME].Get<std::string>().empty()) {
        context_->accessee.bundleName = jsonObject[TAG_PEER_BUNDLE_NAME].Get<std::string>();
        context_->accessee.oldBundleName = context_->accessee.bundleName;
    } else {
        context_->accessee.oldBundleName = context_->pkgName;
    }
    context_->accesser.pkgName = context_->pkgName;
    context_->accessee.pkgName = context_->accesser.pkgName;
    if (jsonObject[TAG_PEER_PKG_NAME].IsString()) {
        context_->accessee.pkgName = jsonObject[TAG_PEER_PKG_NAME].Get<std::string>();
    }
    if (jsonObject[TAG_LOCAL_DISPLAY_ID].IsNumberInteger()) {
        context_->accesser.displayId = jsonObject[TAG_LOCAL_DISPLAY_ID].Get<int32_t>();
    }
    if (jsonObject[TAG_PEER_DISPLAY_ID].IsNumberInteger()) {
        context_->accessee.displayId = jsonObject[TAG_PEER_DISPLAY_ID].Get<int32_t>();
    }
    if (jsonObject[TAG_LOCAL_USERID].IsNumberInteger()) {
        context_->accesser.userId = jsonObject[TAG_LOCAL_USERID].Get<int32_t>();
    } else {
        bool isSystemSA = false;
        {
            std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
            if (bindParam_.find(BIND_CALLER_IS_SYSTEM_SA) != bindParam_.end()) {
                isSystemSA = static_cast<bool>(std::atoi(bindParam_[BIND_CALLER_IS_SYSTEM_SA].c_str()));
            }
        }
        if (!isSystemSA && context_->processInfo.userId > 0) {
            context_->accesser.userId = context_->processInfo.userId;
            LOGI("Hap caller, use processInfo.userId: %{public}d", context_->accesser.userId);
        } else {
            context_->accesser.userId = GetSrcUserIdByDisplayIdAndDeviceType(context_->accesser.displayId,
                static_cast<DmDeviceType>(context_->accesser.deviceType));
            LOGI("SA caller, use displayId to get userId: %{public}d", context_->accesser.userId);
        }
    }
    if (jsonObject[TAG_PEER_USER_ID].IsNumberInteger()) {
        context_->accessee.userId = jsonObject[TAG_PEER_USER_ID].Get<int32_t>();
    }
    return ;
}

int32_t AuthManager::GetSrcUserIdByDisplayIdAndDeviceType(int32_t displayId, DmDeviceType deviceType)
{
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    LOGI("displayId = %{public}d", displayId);
    if (deviceType == DmDeviceType::DEVICE_TYPE_CAR) {
        return GetSrcCarUserIdByDisplayId(displayId);
    }
    return MultipleUserConnector::GetUserIdByDisplayId(displayId);
}

int32_t AuthManager::GetSrcCarUserIdByDisplayId(int32_t displayId)
{
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    LOGI("start.");
    int32_t mainScreenUserId = MultipleUserConnector::GetUserIdByDisplayId(MAIN_SCREEN_DISPLAYID);
    if (mainScreenUserId < 0) {
        LOGE("mainScreenUserId = %{public}d is invalid.", mainScreenUserId);
        return INVALID_USERID;
    }
    bool isSystemSA = false;
    if (bindParam_.find(BIND_CALLER_IS_SYSTEM_SA) != bindParam_.end()) {
        isSystemSA = static_cast<bool>(std::atoi(bindParam_[BIND_CALLER_IS_SYSTEM_SA].c_str()));
    }
    if (isSystemSA) {
        if (displayId == -1) {
            LOGI("not transmit local displayId, return mainScreenUserId");
            return mainScreenUserId;
        }
        if (displayId != MAIN_SCREEN_DISPLAYID) {
            LOGE("accesser.displayId = %{public}d is not control screen.", displayId);
            return INVALID_USERID;
        }
        return mainScreenUserId;
    }
    if (context_->processInfo.userId != mainScreenUserId) {
        LOGE("hap userId and mainScreenUserId is not same.");
        return INVALID_USERID;
    }
    return mainScreenUserId;
}

void AuthManager::ParseServiceInfo(const std::string &extra)
{
    JsonObject jsonObject(extra);
    if (context_ == nullptr || jsonObject.IsDiscarded() || !IsString(jsonObject, PARAM_KEY_IS_SERVICE_BIND) ||
        jsonObject[PARAM_KEY_IS_SERVICE_BIND].Get<std::string>() != DM_VAL_TRUE) {
        return;
    }
    context_->isServiceBind = true;
}

void AuthManager::ParseUltrasonicSide(const JsonObject &jsonObject)
{
    CHECK_NULL_VOID(context_);
    if (jsonObject[TAG_ULTRASONIC_SIDE].IsString()) {
        std::string tempInfo = jsonObject[TAG_ULTRASONIC_SIDE].Get<std::string>();
        if (tempInfo.length() > 0 && isdigit(tempInfo[0])) {
            int32_t intTempInfo = std::atoi(tempInfo.c_str());
            if (intTempInfo == DM_ULTRASONIC_REVERSE) {
                context_->ultrasonicInfo = DmUltrasonicInfo::DM_Ultrasonic_Reverse;
            } else if (intTempInfo == DM_ULTRASONIC_FORWARD) {
                context_->ultrasonicInfo = DmUltrasonicInfo::DM_Ultrasonic_Forward;
            } else {
                context_->ultrasonicInfo = DmUltrasonicInfo::DM_Ultrasonic_Invalid;
                return;
            }
        }
    }
    bool isSupport = true;
    if (context_->ultrasonicInfo == DM_Ultrasonic_Forward) {
#ifdef SUPPORT_MSDP
        isSupport = Msdp::SpatialAwarenessMgrClient::GetInstance().IsPinCodeAbilitySupport(
            Msdp::PinCodeMode::MODE_PIN_RECEIVE_CODE);
#endif
    }
    if (context_->ultrasonicInfo == DM_Ultrasonic_Reverse) {
#ifdef SUPPORT_MSDP
        isSupport = Msdp::SpatialAwarenessMgrClient::GetInstance().IsPinCodeAbilitySupport(
            Msdp::PinCodeMode::MODE_PIN_SEND_CODE);
#endif
    }
    if (!isSupport) {
        context_->authType = AUTH_TYPE_PIN;
    }
}

bool CheckBindLevel(const JsonItemObject &jsonObj, const std::string &key, int32_t &bindLevel)
{
    if (IsJsonValIntegerString(jsonObj, TAG_BIND_LEVEL)) {
        bindLevel = std::atoi(jsonObj[TAG_BIND_LEVEL].Get<std::string>().c_str());
        return true;
    }
    if (IsInt32(jsonObj, TAG_BIND_LEVEL)) {
        bindLevel = jsonObj[TAG_BIND_LEVEL].Get<int32_t>();
        return true;
    }
    return false;
}

int32_t AuthManager::GetBindLevel(int32_t bindLevel)
{
    LOGI("start.");
    std::string processName = "";
    bool isSystemSA = false;
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        if (bindParam_.find("bindCallerProcessName") != bindParam_.end()) {
            processName = bindParam_["bindCallerProcessName"];
        }
        if (bindParam_.find("bindCallerIsSystemSA") != bindParam_.end()) {
            isSystemSA = static_cast<bool>(std::atoi(bindParam_["bindCallerIsSystemSA"].c_str()));
        }
    }
    LOGI("processName = %{public}s, isSystemSA %{public}d.", GetAnonyString(processName).c_str(), isSystemSA);
    if (processName != "" && AuthManagerBase::CheckProcessNameInWhiteList(processName)) {
        return USER;
    }
    if (isSystemSA) {
        if (static_cast<uint32_t>(bindLevel) == INVALIED_TYPE || static_cast<uint32_t>(bindLevel) > APP ||
            static_cast<uint32_t>(bindLevel) < USER) {
            return USER;
        }
        return bindLevel;
    }
    if (static_cast<uint32_t>(bindLevel) == INVALIED_TYPE || (static_cast<uint32_t>(bindLevel) != APP &&
        static_cast<uint32_t>(bindLevel) != SERVICE)) {
        return APP;
    }
    return bindLevel;
}

void AuthManager::GetAuthParam(const std::string &pkgName, int32_t authType,
    const std::string &deviceId, const std::string &extra)
{
    LOGI("Get auth param with pkgName %{public}s.", pkgName.c_str());
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    CHECK_NULL_VOID(context_);
    context_->accesser.deviceId = std::string(localDeviceId);
    context_->pkgName = pkgName;
    context_->authType = (DmAuthType)authType;
    context_->accesser.deviceName = context_->listener->GetLocalDisplayDeviceName();
    context_->accesser.deviceType = context_->softbusConnector->GetLocalDeviceTypeId();
    context_->accesser.isOnline = false;

    context_->accessee.deviceId = deviceId;
    context_->accessee.addr = deviceId;
    JsonObject jsonObject(extra);
    if (jsonObject.IsDiscarded()) {
        LOGE("extra string not a json type.");
        return;
    }
    ParseJsonObject(jsonObject);
    if (context_->isServiceBind) {
        if (IsNumberString(deviceId)) {
            context_->accessee.serviceId = std::atoll(deviceId.c_str()); // service bind device id is service id
            context_->accesser.serviceId = context_->accessee.serviceId;
        } else {
            LOGE("OpenAuthSession failed");
            return;
        }
    }
#ifdef CAR_DEVICE_ENABLE
    DMAccountInfo dmAccountInfo = MultipleUserConnector::GetDMAccountInfoByUserId(context_->accesser.userId);
    context_->accesser.accountId = dmAccountInfo.accountId;
#else
    context_->accesser.accountId = MultipleUserConnector::GetOhosAccountIdByUserId(context_->accesser.userId);
#endif
    // compatible for old version
    context_->accesser.oldBindLevel = INVALIED_TYPE;
    CheckBindLevel(jsonObject, TAG_BIND_LEVEL, context_->accesser.oldBindLevel);
    context_->accesser.oldBindLevel = GetBindLevel(context_->accesser.oldBindLevel);
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        bindParam_["bindCallerOldBindLevel"] = std::to_string(context_->accesser.oldBindLevel);
    }
    LOGI("bindCallerOldBindLevel %{public}d.", context_->accesser.oldBindLevel);
}

void AuthManager::InitAuthState(const std::string &pkgName, int32_t authType,
    const std::string &deviceId, const std::string &extra)
{
    CHECK_NULL_VOID(context_);
    auto iter = context_->authenticationMap.find(authType);
    if (iter != context_->authenticationMap.end()) {
        context_->authPtr = iter->second;
    }
    CHECK_NULL_VOID(context_->timer);
    context_->timer->StartTimer(std::string(AUTHENTICATE_TIMEOUT_TASK),
        AUTHENTICATE_TIMEOUT,
        [this] (std::string name) {
            DmAuthState::HandleAuthenticateTimeout(context_, name);
        });
    GetAuthParam(pkgName, authType, deviceId, extra);
    CHECK_NULL_VOID(context_->authStateMachine);
    context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcStartState>());
    LOGI("complete");
    return;
}
int32_t AuthManager::AuthenticateDevice(const std::string &pkgName, int32_t authType,
    const std::string &deviceId, const std::string &extra)
{
    LOGI("start auth type %{public}d.", authType);
    SetAuthType(authType);
    ParseServiceInfo(extra);
    int32_t ret = DM_OK;
    if (context_->isServiceBind) {
        ret = CheckSrcNegotiateSrvParam(pkgName, targetId_.serviceId, bindParam_);
        if (ret != DM_OK) {
            return ERR_DM_INPUT_PARA_INVALID;
        }
    }
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    context_->processInfo.pkgName = pkgName;
    GetBindCallerInfo();
    ret = CheckAuthParamVaild(pkgName, authType, deviceId, extra);
    if (ret != DM_OK) {
        return ret;
    }
    ret = CheckProxyAuthParamVaild(extra);
    if (ret != DM_OK) {
        LOGE("CheckProxyAuthParamVaild failed.");
        return ret;
    }
    context_->isAuthenticateDevice = true;
    if (authType == AUTH_TYPE_CRE) {
        GetConnDelayCloseTime(extra);
        LOGI("credential type, joinLNN directly.");
        CHECK_NULL_RETURN(context_->softbusConnector, ERR_DM_POINT_NULL);
        context_->softbusConnector->JoinLnn(deviceId, true);
        CHECK_NULL_RETURN(context_->listener, ERR_DM_POINT_NULL);
        context_->listener->OnAuthResult(context_->processInfo, context_->peerTargetId.deviceId,
            "", STATUS_DM_AUTH_DEFAULT, DM_OK);
        context_->listener->OnBindResult(context_->processInfo, context_->peerTargetId,
            DM_OK, STATUS_DM_AUTH_DEFAULT, "");
        context_->reason = DM_OK;
        CHECK_NULL_RETURN(context_->authStateMachine, ERR_DM_POINT_NULL);
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcFinishState>());
        return DM_OK;
    }
    InitAuthState(pkgName, authType, deviceId, extra);
    if (context_->accesser.userId < 0) {
        LOGE("accesser.userId is invalid.");
        return ERR_DM_GET_LOCAL_USERID_FAILED;
    }
    if (context_->ultrasonicInfo == DmUltrasonicInfo::DM_Ultrasonic_Invalid) {
        return ERR_DM_INPUT_PARA_INVALID;
    }
    return DM_OK;
}

void AuthManager::GetConnDelayCloseTime(const std::string &extra)
{
    JsonObject jsonObject(extra);
    if (jsonObject.IsDiscarded()) {
        LOGE("extra string not a json type.");
        return;
    }
    CHECK_NULL_VOID(context_);
    GetDelayCloseConnTime(jsonObject);
}

int32_t AuthManager::CheckSrcNegotiateSrvParam(const std::string &pkgName, int64_t serviceId,
    const std::map<std::string, std::string> &bindParam)
{
    LOGI("source eegotiate service param start.");
    if (pkgName.empty() || serviceId == 0) {
        LOGE("param failed, pkgName or service id is empty.");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    auto iterService = bindParam.find(PARAM_KEY_SUBJECT_SERVICE_ONES);
    auto iter = bindParam.find(PARAM_KEY_IS_PROXY_BIND);
    if (iter == bindParam.end()) {
        return DM_OK;
    }
    std::string isProxyBind = iter->second;
    if (isProxyBind == "true" && iterService == bindParam.end()) {
        LOGE("param failed, proxyed subjects is empty.");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    return DM_OK;
}

int32_t AuthManager::BindTarget(const std::string &pkgName, const PeerTargetId &targetId,
    const std::map<std::string, std::string> &bindParam, int sessionId, uint64_t logicalSessionId)
{
    int ret = DM_OK;
    LOGI("start. pkgName: %{public}s", pkgName.c_str());

    struct RadarInfo info = {
        .funcName = "AuthenticateDevice",
        .stageRes = static_cast<int32_t>(StageRes::STAGE_SUCC),
        .bizState = static_cast<int32_t>(BizState::BIZ_STATE_END),
    };
    if (!DmRadarHelper::GetInstance().ReportDiscoverUserRes(info)) {
        LOGE("ReportDiscoverUserRes failed");
    }
    GetIsNeedJoinLnnParam(bindParam);
    if (pkgName.empty()) {
        LOGE("pkgName is empty.");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    int32_t authType = -1;
    if (ParseAuthType(bindParam, authType) != DM_OK) {
        LOGE("key: %{public}s error.", PARAM_KEY_AUTH_TYPE);
        return ERR_DM_INPUT_PARA_INVALID;
    }
    CHECK_NULL_RETURN(context_, ERR_DM_POINT_NULL);
    context_->peerTargetId = targetId_;
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        bindParam_ = bindParam;
    }
    if (!targetId.deviceId.empty()) {
        ret = AuthenticateDevice(pkgName, authType, targetId.deviceId, ParseExtraFromMap(bindParam));
        if (ret != DM_OK) { return ret; }
    } else {
        LOGE("targetId is error.");
        return ERR_DM_INPUT_PARA_INVALID;
    }

    context_->sessionId = sessionId;
    context_->logicalSessionId = logicalSessionId;
    context_->requestId = static_cast<int64_t>(logicalSessionId);
    CHECK_NULL_RETURN(context_->authStateMachine, ERR_DM_POINT_NULL);
    context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcNegotiateStateMachine>());
    info = { .funcName = "BindTarget" };
    info.channelId = sessionId;
    DmRadarHelper::GetInstance().ReportAuthSendRequest(info);
    return ret;
}

void AuthManager::GetIsNeedJoinLnnParam(const std::map<std::string, std::string> &bindParam)
{
    std::string isNeedJoinLnnStr;
    if (bindParam.find(IS_NEED_JOIN_LNN) != bindParam.end()) {
        isNeedJoinLnnStr = bindParam.at(IS_NEED_JOIN_LNN);
    }
    CHECK_NULL_VOID(context_);
    if (isNeedJoinLnnStr == NEED_JOIN_LNN || isNeedJoinLnnStr == NO_NEED_JOIN_LNN) {
        context_->isNeedJoinLnn = std::atoi(isNeedJoinLnnStr.c_str());
        LOGI("isNeedJoinLnn: %{public}d.", context_->isNeedJoinLnn);
    }
}

AuthSinkManager::AuthSinkManager(std::shared_ptr<SoftbusConnector> softbusConnector,
    std::shared_ptr<HiChainConnector> hiChainConnector,
    std::shared_ptr<IDeviceManagerServiceListener> listener,
    std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)
    : AuthManager(softbusConnector, hiChainConnector, listener, hiChainAuthConnector)
{
    context_->direction = DM_AUTH_SINK;
    context_->authStateMachine = std::make_shared<DmAuthStateMachine>(context_);
}

void AuthSinkManager::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result)
{
    LOGI("sessionId = %{public}d and sessionSide = %{public}d result = %{public}d", sessionId, sessionSide, result);
}

void AuthSinkManager::OnSessionClosed(int32_t sessionId)
{
    LOGI("sessionId = %{public}d", sessionId);
    CHECK_NULL_VOID(context_);
    context_->reason = ERR_DM_SESSION_CLOSED;
    context_->authStateMachine->TransitionTo(std::make_shared<AuthSinkFinishState>());
}

void AuthSinkManager::OnDataReceived(int32_t sessionId, std::string message)
{
    CHECK_NULL_VOID(context_);
    context_->sessionId = sessionId;
    int32_t ret = context_->authMessageProcessor->ParseMessage(context_, message);
    if (ret != DM_OK) {
        LOGE("parse input message error.");
        context_->reason = ERR_DM_PARSE_MESSAGE_FAILED;
        CHECK_NULL_VOID(context_->authStateMachine);
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSinkFinishState>());
    }

    return;
}

bool AuthSinkManager::GetIsCryptoSupport()
{
    return false;
}

void AuthManager::GetRemoteDeviceId(std::string &deviceId)
{
    CHECK_NULL_VOID(context_);
    deviceId = (context_->direction == DM_AUTH_SOURCE) ? context_->accessee.deviceId : context_->accesser.deviceId;
    return;
}

int32_t AuthSinkManager::OnUserOperation(int32_t action, const std::string &params)
{
    LOGI("action %{public}d.", action);
    if (context_ == nullptr || context_->authStateMachine == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }
    switch (action) {
        case USER_OPERATION_TYPE_CANCEL_AUTH:
        case USER_OPERATION_TYPE_ALLOW_AUTH:
        case USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS:
            context_->confirmOperation = static_cast<UiAction>(action);
            context_->reply = USER_OPERATION_TYPE_ALLOW_AUTH;
            context_->userOperationParam = params;
            if (action == USER_OPERATION_TYPE_CANCEL_AUTH) {
                LOGI("USER_OPERATION_TYPE_CANCEL_AUTH.");
                context_->reply = USER_OPERATION_TYPE_CANCEL_AUTH;
            }
            context_->authStateMachine->NotifyEventFinish(DmEventType::ON_USER_OPERATION);
            if (!context_->businessId.empty()) {
                HandleBusinessEvents(context_->businessId, action);
            }
            break;
        case USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT:
            LOGI("USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT.");
            context_->confirmOperation = USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT;
            context_->reason = ERR_DM_PEER_CONFIRM_TIME_OUT;
            context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
            if (!context_->businessId.empty()) {
                HandleBusinessEvents(context_->businessId, action);
            }
            break;
        case USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY:
            LOGI("USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY.");
            context_->confirmOperation = USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY;
            context_->reason = ERR_DM_BIND_USER_CANCEL_PIN_CODE_DISPLAY;
            context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
            break;
        default:
            LOGE("this action id not support");
            break;
    }
    LOGI("leave.");
    return DM_OK;
}

AuthSrcManager::AuthSrcManager(std::shared_ptr<SoftbusConnector> softbusConnector,
    std::shared_ptr<HiChainConnector> hiChainConnector,
    std::shared_ptr<IDeviceManagerServiceListener> listener,
    std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)
    : AuthManager(softbusConnector, hiChainConnector, listener, hiChainAuthConnector)
{
    context_->direction = DM_AUTH_SOURCE;
    context_->authStateMachine = std::make_shared<DmAuthStateMachine>(context_);
}

void AuthSrcManager::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result)
{
    LOGI("sessionId = %{public}d and sessionSide = %{public}d result = %{public}d", sessionId, sessionSide, result);
}

void AuthSrcManager::OnSessionClosed(int32_t sessionId)
{
    LOGI("sessionId = %{public}d", sessionId);
    CHECK_NULL_VOID(context_);
    context_->reason = ERR_DM_SESSION_CLOSED;
    CHECK_NULL_VOID(context_->authStateMachine);
    context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcFinishState>());
}

void AuthSrcManager::OnSessionDisable()
{
    CHECK_NULL_VOID(context_);
    context_->sessionId = -1;
}

void AuthSrcManager::OnDataReceived(int32_t sessionId, std::string message)
{
    CHECK_NULL_VOID(context_);
    context_->sessionId = sessionId;
    CHECK_NULL_VOID(context_->authMessageProcessor);
    int32_t ret = context_->authMessageProcessor->ParseMessage(context_, message);
    if (ret != DM_OK) {
        LOGE("parse input message error.");
        context_->reason = ERR_DM_PARSE_MESSAGE_FAILED;
        CHECK_NULL_VOID(context_->authStateMachine);
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcFinishState>());
    }

    return;
}

bool AuthSrcManager::GetIsCryptoSupport()
{
    return false;
}

int32_t AuthSrcManager::OnUserOperation(int32_t action, const std::string &params)
{
    LOGI("start.");
    if (context_ == nullptr || context_->authStateMachine == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }

    JsonObject paramJson;
    paramJson.Parse(params);
    std::string pinCode;
    switch (action) {
        case USER_OPERATION_TYPE_CANCEL_PINCODE_INPUT:
            LOGE("AuthSrcManager OnUserOperation user cancel");
            context_->pinInputResult = USER_OPERATION_TYPE_CANCEL_PINCODE_INPUT;
            context_->reason = ERR_DM_BIND_USER_CANCEL_ERROR;
            context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
            break;
        case USER_OPERATION_TYPE_DONE_PINCODE_INPUT:
            LOGE("AuthSrcManager OnUserOperation user input done");
            context_->pinInputResult = USER_OPERATION_TYPE_DONE_PINCODE_INPUT;
            if (paramJson.IsDiscarded() || !IsString(paramJson, PIN_CODE_KEY)) {
                LOGE("AuthSrcManager OnUserOperation pinCode not found");
                return ERR_DM_INPUT_PARA_INVALID;
            }
            pinCode = paramJson[PIN_CODE_KEY].Get<std::string>();
            {
                if (!IsNumberString(pinCode)) {
                    LOGE("jsonStr error");
                    return ERR_DM_INPUT_PARA_INVALID;
                }
                context_->pinCode = pinCode;
            }
            context_->authStateMachine->NotifyEventFinish(DmEventType::ON_USER_OPERATION);
            break;
        default:
            LOGE("this action id not support");
            break;
    }
    LOGI("leave.");
    return DM_OK;
}

void AuthSrcManager::AuthDeviceError(int64_t requestId, int32_t errorCode)
{
    LOGI("start.");
    CHECK_NULL_VOID(context_);
    if (requestId != context_->requestId) {
        LOGE("requestId: %{public}" PRId64", context_->requestId: %{public}" PRId64".", requestId, context_->requestId);
        return;
    }
    CHECK_NULL_VOID(context_->authStateMachine);
    auto curState = context_->authStateMachine->GetCurState();
    if (curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_START_STATE ||
        curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_MSG_NEGOTIATE_STATE ||
        curState == DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE) {
        LOGI("Auth pin err.");
        if (context_->authType == DmAuthType::AUTH_TYPE_PIN) {
            context_->inputPinAuthFailTimes++;
        }
        context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR);
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcPinNegotiateStartState>());
    } else {
        LOGI("unexpected err.");
        context_->reason = (errorCode == ERR_DM_HICHAIN_PROOFMISMATCH ? ERR_DM_BIND_PIN_CODE_ERROR : errorCode);
        context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
    }
    LOGI("leave.");
}

void AuthSinkManager::AuthDeviceError(int64_t requestId, int32_t errorCode)
{
    LOGI("start.");
    CHECK_NULL_VOID(context_);
    CHECK_NULL_VOID(context_->authStateMachine);
    auto curState = context_->authStateMachine->GetCurState();
    if (curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE ||
        curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_MSG_NEGOTIATE_STATE) {
        LOGI("Auth pin err.");
        if (context_->authType == DmAuthType::AUTH_TYPE_PIN) {
            context_->inputPinAuthFailTimes++;
        }
        context_->authStateMachine->NotifyEventFinish(DmEventType::ON_ERROR);
        context_->authStateMachine->TransitionTo(std::make_shared<AuthSinkPinNegotiateStartState>());
    } else {
        LOGI("unexpected err.");
        context_->reason = errorCode;
        context_->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
    }
    LOGI("leave.");
}

bool AuthSrcManager::AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen)
{
    LOGI("start.");
    // check request id first
    CHECK_NULL_RETURN(context_, false);
    if (requestId != context_->requestId) {
        LOGE("requestId %{public}" PRId64"is error.", requestId);
        return false;
    }

    context_->transmitData = std::string(reinterpret_cast<const char *>(data), dataLen);
    CHECK_NULL_RETURN(context_->authStateMachine, false);
    context_->authStateMachine->NotifyEventFinish(ON_TRANSMIT);
    LOGI("leave.");
    return true;
}

bool AuthSinkManager::AuthDeviceTransmit(int64_t requestId, const uint8_t *data, uint32_t dataLen)
{
    LOGI("start.");
    // check request id first
    CHECK_NULL_RETURN(context_, false);
    if (requestId != context_->requestId) {
        LOGE("requestId %{public}" PRId64"is error.", requestId);
        return false;
    }

    context_->transmitData = std::string(reinterpret_cast<const char *>(data), dataLen);
    CHECK_NULL_RETURN(context_->authStateMachine, false);
    context_->authStateMachine->NotifyEventFinish(ON_TRANSMIT);
    LOGI("leave.");
    return true;
}

void AuthSrcManager::AuthDeviceFinish(int64_t requestId)
{
    LOGI("start.");
    CHECK_NULL_VOID(context_);
    CHECK_NULL_VOID(context_->authStateMachine);
    context_->authStateMachine->NotifyEventFinish(ON_FINISH);
    // Perform business processing based on the current state
    DmAuthStateType curState = context_->authStateMachine->GetCurState();
    switch (curState) {
        case DmAuthStateType::AUTH_SRC_PIN_AUTH_DONE_STATE:
            if (!context_->isNeedAuthenticate) {
                LOGI("skip authenticate.");
                context_->reason = ERR_DM_SKIP_AUTHENTICATE;
                context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcFinishState>());
            } else {
                // ON_FINISH event occurs, start credential exchange
                context_->authStateMachine->TransitionTo(std::make_shared<AuthSrcCredentialExchangeState>());
            }
            break;
        default:
            break;
    }
    LOGI("leave.");
}

void AuthSinkManager::AuthDeviceFinish(int64_t requestId)
{
    LOGI("start.");
    CHECK_NULL_VOID(context_);
    CHECK_NULL_VOID(context_->authStateMachine);
    context_->authStateMachine->NotifyEventFinish(ON_FINISH);
    LOGI("leave.");
}

void AuthSinkManager::AuthDeviceSessionKey(int64_t requestId, const uint8_t *sessionKey, uint32_t sessionKeyLen)
{
    LOGI("start. keyLen: %{public}u", sessionKeyLen);
    if (context_ == nullptr || context_->authMessageProcessor == nullptr || context_->authStateMachine == nullptr) {
        LOGE("auth context not initial.");
        return;
    }
    if (requestId != context_->requestId) {
        LOGE("requestId %{public}" PRId64 "is error.", requestId);
        return;
    }
    int32_t ret = context_->authMessageProcessor->SaveSessionKey(sessionKey, sessionKeyLen);
    if (ret != DM_OK) {
        LOGE("save session key error, ret: %{public}d", ret);
    }

    context_->authStateMachine->NotifyEventFinish(ON_SESSION_KEY_RETURNED);
}

char *AuthSinkManager::AuthDeviceRequest(int64_t requestId, int operationCode, const char *reqParams)
{
    LOGI("start");
    (void)requestId;
    (void)reqParams;
    JsonObject jsonObj;

    DmAuthStateType curState = context_->authStateMachine->GetCurState();
    if (curState == DmAuthStateType::AUTH_SINK_PIN_AUTH_START_STATE ||
        curState == DmAuthStateType::AUTH_SINK_REVERSE_ULTRASONIC_DONE_STATE||
        curState == DmAuthStateType::AUTH_SINK_FORWARD_ULTRASONIC_DONE_STATE) {
        std::string pinCode = "";
        if (GetPinCode(pinCode) == ERR_DM_FAILED || pinCode == "") {
            jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_REJECTED;
        } else {
            jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED;
            jsonObj[FIELD_PIN_CODE] = pinCode;
        }
        std::string pinCodeHash = GetAnonyString(Crypto::Sha256(pinCode));
        LOGI("pinCodeHash: %{public}s", pinCodeHash.c_str());
    } else if (curState == DmAuthStateType::AUTH_SINK_CREDENTIAL_AUTH_START_STATE) {
        if (context_->isOnline) { // Non-first time certification
            jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED;
            jsonObj[FIELD_CRED_ID] = context_->accessee.transmitCredentialId;
        } else if (!context_->isAppCredentialVerified) { // First-time authentication &&  appCred auth
            jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED;
            jsonObj[FIELD_CRED_ID] = context_->accessee.transmitCredentialId;
        } else {  // First-time authentication && User credential authentication
            jsonObj[FIELD_CONFIRMATION] = RequestResponse::REQUEST_ACCEPTED;
            jsonObj[FIELD_CRED_ID] = context_->accessee.lnnCredentialId;
        }
    }
    jsonObj[FIELD_SERVICE_PKG_NAME] = std::string(DM_PKG_NAME);
    std::string jsonStr = jsonObj.Dump();
    char *buffer = strdup(jsonStr.c_str());
    return buffer;
}

int32_t AuthManager::GetPinCode(std::string &code)
{
    if (context_ == nullptr) {
        LOGE("AuthManager failed to GetPinCode because context_ is nullptr");
        return ERR_DM_FAILED;
    }
    std::string pinCodeHash = GetAnonyString(Crypto::Sha256(context_->pinCode));
    LOGI("pinCodeHash: %{public}s", pinCodeHash.c_str());
    code = context_->pinCode;
    return DM_OK;
}

// Reacquire BindParams to rebuild the link, generally used when switching between old and new protocol objects
void AuthManager::GetBindTargetParams(std::string &pkgName, PeerTargetId &targetId,
    std::map<std::string, std::string> &bindParam)
{
    CHECK_NULL_VOID(context_);
    pkgName = context_->pkgName;
    targetId = targetId_;
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        bindParam = bindParam_;
    }
    LOGI("get pkgName %{public}s to reuse", pkgName.c_str());
    return;
}

void AuthManager::GetAuthCodeAndPkgName(std::string &pkgName, std::string &authCode)
{
    if (context_ == nullptr || context_->importAuthCode.empty() || context_->importPkgName.empty()) {
        LOGE("authCode or pkgName is empty");
        return;
    }
    authCode = context_->importAuthCode;
    pkgName = context_->importPkgName;
}

void AuthManager::SetBindTargetParams(const PeerTargetId &targetId)
{
    targetId_ = targetId;
    LOGI("set targetId to reuse");
    return;
}

void AuthManager::ClearSoftbusSessionCallback()
{}

void AuthManager::PrepareSoftbusSessionCallback()
{}

void AuthManager::GetBindCallerInfo()
{
    LOGI("start.");
    CHECK_NULL_VOID(context_);
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        if (bindParam_.find("bindCallerUserId") != bindParam_.end()) {
            context_->processInfo.userId = std::atoi(bindParam_["bindCallerUserId"].c_str());
        }
        if (bindParam_.find("bindCallerTokenId") != bindParam_.end()) {
            context_->accesser.tokenId = std::atoi(bindParam_["bindCallerTokenId"].c_str());
        }
        if (bindParam_.find("bindCallerBindLevel") != bindParam_.end()) {
            context_->accesser.bindLevel = std::atoi(bindParam_["bindCallerBindLevel"].c_str());
        }
        if (bindParam_.find("bindCallerBundleName") != bindParam_.end()) {
            context_->accesser.bundleName = bindParam_["bindCallerBundleName"];
        }
        if (bindParam_.find("bindCallerHostPkgLabel") != bindParam_.end()) {
            context_->pkgLabel = bindParam_["bindCallerHostPkgLabel"];
        }
    }
}

void AuthManager::DeleteTimer()
{
    if (context_ != nullptr) {
        context_->successFinished = true;
        context_->authStateMachine->Stop();  // Stop statemMachine thread
        context_->timer->DeleteAll();
        LOGI("AuthManager context deleteTimer successful.");
    }
    {
        std::lock_guard<ffrt::mutex> lock(bindParamMutex_);
        bindParam_.clear();
    }
    LOGI("end.");
}

//LCOV_EXCL_START
int32_t AuthManager::HandleBusinessEvents(const std::string &businessId, int32_t action)
{
    LOGI("businessId %{public}s, action %{public}d.", businessId.c_str(), action);
    DistributedDeviceProfile::BusinessEvent rejectEvent;
    rejectEvent.SetBusinessKey(DM_REJECT_KEY);
    JsonObject rejectJson;
    rejectJson[DM_BUSINESS_ID] = businessId;
    rejectJson[DM_AUTH_DIALOG_REJECT] =
        (action == USER_OPERATION_TYPE_CANCEL_AUTH || action == USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT);
    rejectJson[DM_TIMESTAMP] = std::to_string(GetCurrentTimestamp());
    rejectEvent.SetBusinessValue(rejectJson.Dump());
    int32_t ret = DistributedDeviceProfile::DistributedDeviceProfileClient::GetInstance().PutBusinessEvent(rejectEvent);
    if (ret != DM_OK) {
        LOGE("HandleBusinessEvents failed to store reject_event, ret: %{public}d", ret);
        return ret;
    }
    LOGI("HandleBusinessEvents successfully stored reject_event.");
    return DM_OK;
}
int32_t AuthManager::CheckProxyAuthParamVaild(const std::string &extra)
{
    LOGI("start.");
    JsonObject jsonObject(extra);
    if (jsonObject.IsDiscarded() || !IsString(jsonObject, PARAM_KEY_IS_PROXY_BIND)) {
        return DM_OK;
    }
    if (jsonObject[PARAM_KEY_IS_PROXY_BIND].Get<std::string>() != DM_VAL_TRUE) {
        return DM_OK;
    }
    bool isSystemSA = false;
    if (bindParam_.find(BIND_CALLER_IS_SYSTEM_SA) != bindParam_.end()) {
        isSystemSA = static_cast<bool>(std::atoi(bindParam_[BIND_CALLER_IS_SYSTEM_SA].c_str()));
    }
    if (!isSystemSA) {
        LOGE("no proxy permission");
        return ERR_DM_NO_PERMISSION;
    }

    if (context_->isServiceBind) {
        LOGI("CheckServiceAuthParamVaild enter");
        return CheckServiceAuthParamVaild(jsonObject);
    }
    if (!jsonObject.Contains(PARAM_KEY_SUBJECT_PROXYED_SUBJECTS) ||
        !IsString(jsonObject, PARAM_KEY_SUBJECT_PROXYED_SUBJECTS)) {
        LOGE("no subject proxyed apps");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    std::string subjectProxyOnesStr = jsonObject[PARAM_KEY_SUBJECT_PROXYED_SUBJECTS].Get<std::string>();
    JsonObject allProxyObj;
    allProxyObj.Parse(subjectProxyOnesStr);
    for (auto const &item : allProxyObj.Items()) {
        if (!item.Contains(TAG_BUNDLE_NAME) || !IsString(item, TAG_BUNDLE_NAME)) {
            LOGE("bundleName invalid");
            return ERR_DM_INPUT_PARA_INVALID;
        }
        if (!item.Contains(TAG_TOKENID) || !IsInt64(item, TAG_TOKENID)) {
            LOGE("tokenId invalid");
            return ERR_DM_INPUT_PARA_INVALID;
        }
    }
    return DM_OK;
}

int32_t AuthManager::CheckServiceAuthParamVaild(const JsonObject &jsonObject)
{
    LOGI("start.");
    if (!jsonObject.Contains(PARAM_KEY_SUBJECT_SERVICE_ONES) ||
        !IsString(jsonObject, PARAM_KEY_SUBJECT_SERVICE_ONES)) {
        LOGE("no subject proxyed services");
        return ERR_DM_INPUT_PARA_INVALID;
    }
    std::string subjectServiceOnesStr = jsonObject[PARAM_KEY_SUBJECT_SERVICE_ONES].Get<std::string>();
    JsonObject allServiceObj;
    allServiceObj.Parse(subjectServiceOnesStr);
    for (auto const &item : allServiceObj.Items()) {
        if (!item.Contains(PARAM_KEY_LOCAL_PKGNAME) || !IsString(item, PARAM_KEY_LOCAL_PKGNAME)) {
            LOGE("pkgName invalid");
            return ERR_DM_INPUT_PARA_INVALID;
        }
        if (!item.Contains(PARAM_KEY_LOCAL_TOKENID) || !IsString(item, PARAM_KEY_LOCAL_TOKENID)) {
            LOGE("tokenId invalid");
            return ERR_DM_INPUT_PARA_INVALID;
        }
        if (!item.Contains(PARAM_KEY_PEER_SERVICEID) || !IsString(item, PARAM_KEY_PEER_SERVICEID)) {
            LOGE("serviceId invalid");
            return ERR_DM_INPUT_PARA_INVALID;
        }
    }
    return DM_OK;
}

void AuthManager::ParseProxyJsonObject(const JsonObject &jsonObject)
{
    if (context_ == nullptr || jsonObject.IsDiscarded() || !IsString(jsonObject, PARAM_KEY_IS_PROXY_BIND) ||
        jsonObject[PARAM_KEY_IS_PROXY_BIND].Get<std::string>() != DM_VAL_TRUE) {
        return;
    }
    context_->IsProxyBind = true;
    if (IsString(jsonObject, PARAM_KEY_IS_CALLING_PROXY_AS_SUBJECT) &&
        jsonObject[PARAM_KEY_IS_CALLING_PROXY_AS_SUBJECT].Get<std::string>() == DM_VAL_FALSE) {
        context_->IsCallingProxyAsSubject = false;
    }
    if (!IsString(jsonObject, PARAM_KEY_SUBJECT_PROXYED_SUBJECTS)) {
        LOGE("no subject proxyed apps");
        return;
    }
    std::string subjectProxyOnesStr = jsonObject[PARAM_KEY_SUBJECT_PROXYED_SUBJECTS].Get<std::string>();
    JsonObject allProxyObj;
    allProxyObj.Parse(subjectProxyOnesStr);
    for (auto const &item : allProxyObj.Items()) {
        if (!IsString(item, TAG_BUNDLE_NAME)) {
            LOGE("bundleName invalid");
            return;
        }
        if (!IsInt64(item, TAG_TOKENID)) {
            LOGE("tokenId invalid");
            return;
        }
        std::string bundleName = item[TAG_BUNDLE_NAME].Get<std::string>();
        if (context_->accesser.bundleName == bundleName) {
            LOGE("proxy bundleName same as caller bundleName");
            return;
        }
        std::string peerBundleName = bundleName;
        if (item.Contains(PARAM_KEY_PEER_BUNDLE_NAME) && IsString(item, PARAM_KEY_PEER_BUNDLE_NAME)) {
            peerBundleName = item[PARAM_KEY_PEER_BUNDLE_NAME].Get<std::string>();
        }
        DmProxyAuthContext proxyAuthContext;
        proxyAuthContext.proxyContextId = Crypto::Sha256(bundleName + peerBundleName);
        if (std::find(context_->subjectProxyOnes.begin(), context_->subjectProxyOnes.end(), proxyAuthContext) ==
            context_->subjectProxyOnes.end()) {
            proxyAuthContext.proxyAccesser.bundleName = bundleName;
            proxyAuthContext.proxyAccesser.tokenId = item[TAG_TOKENID].Get<int64_t>();
            proxyAuthContext.proxyAccesser.tokenIdHash =
                Crypto::GetTokenIdHash(std::to_string(proxyAuthContext.proxyAccesser.tokenId));
            proxyAuthContext.proxyAccessee.bundleName = peerBundleName;
            GetBindLevelByBundleName(bundleName, context_->accesser.userId, proxyAuthContext.proxyAccesser.bindLevel);
            context_->subjectProxyOnes.push_back(proxyAuthContext);
        }
    }
}

void AuthManager::ParseServiceJsonObject(const JsonObject &jsonObject)
{
    LOGI("ParseServiceJsonObject inner1");
    if (context_ == nullptr || jsonObject.IsDiscarded() || !IsString(jsonObject, PARAM_KEY_IS_PROXY_BIND) ||
        jsonObject[PARAM_KEY_IS_PROXY_BIND].Get<std::string>() != DM_VAL_TRUE) {
        LOGI("ParseServiceJsonObject inner2");
        return;
    }
    context_->IsProxyBind = true;
    if (IsString(jsonObject, PARAM_KEY_IS_CALLING_PROXY_AS_SUBJECT) &&
        jsonObject[PARAM_KEY_IS_CALLING_PROXY_AS_SUBJECT].Get<std::string>() == DM_VAL_FALSE) {
        context_->IsCallingProxyAsSubject = false;
    }
    if (!IsString(jsonObject, PARAM_KEY_SUBJECT_SERVICE_ONES)) {
        LOGE("no subject proxyed apps");
        return;
    }
    LOGI("ParseServiceJsonObject inner3");
    std::string subjectServiceOnesStr = jsonObject[PARAM_KEY_SUBJECT_SERVICE_ONES].Get<std::string>();
    JsonObject allServiceObj;
    allServiceObj.Parse(subjectServiceOnesStr);
    for (auto const &item : allServiceObj.Items()) {
        if (!IsString(item, PARAM_KEY_LOCAL_PKGNAME)) {
            LOGE("local pkgName invalid");
            return;
        }
        if (!IsString(item, PARAM_KEY_LOCAL_TOKENID)) {
            LOGE("local tokenId invalid");
            return;
        }
        if (!IsString(item, PARAM_KEY_PEER_SERVICEID)) {
            LOGE("peer serviceId invalid");
            return;
        }
        DmProxyAuthContext proxyAuthContext;
        if (std::find(context_->subjectServiceOnes.begin(), context_->subjectServiceOnes.end(), proxyAuthContext) ==
            context_->subjectServiceOnes.end()) {
            proxyAuthContext.proxyAccesser.pkgName = item[PARAM_KEY_LOCAL_PKGNAME].Get<std::string>();
            proxyAuthContext.proxyAccesser.tokenId = std::stoll(item[PARAM_KEY_LOCAL_TOKENID].Get<std::string>());
            proxyAuthContext.proxyAccesser.tokenIdHash =
                Crypto::GetTokenIdHash(std::to_string(proxyAuthContext.proxyAccesser.tokenId));
            proxyAuthContext.proxyAccessee.serviceId = std::stoll(item[PARAM_KEY_PEER_SERVICEID].Get<std::string>());
            proxyAuthContext.proxyContextId = Crypto::Sha256(proxyAuthContext.proxyAccesser.tokenIdHash +
                std::to_string(proxyAuthContext.proxyAccesser.serviceId));
            proxyAuthContext.proxyAccesser.bindLevel = context_->accesser.bindLevel;
            context_->subjectServiceOnes.push_back(proxyAuthContext);
        }
    }
}

void AuthManager::GetBindLevelByBundleName(std::string &bundleName, int32_t userId, int32_t &bindLevel)
{
    int64_t tokenId = 0;
    if (AppManager::GetInstance().GetHapTokenIdByName(userId, bundleName, 0, tokenId) == DM_OK) {
        bindLevel = DmRole::DM_ROLE_FA;
    } else if (AppManager::GetInstance().GetNativeTokenIdByName(bundleName, tokenId) == DM_OK) {
        bindLevel = DmRole::DM_ROLE_SA;
    } else {
        LOGE("src not contain the bundlename %{public}s.", bundleName.c_str());
    }
}

void AuthManager::GetDelayCloseConnTime(const JsonObject &jsonObject)
{
    CHECK_NULL_VOID(context_);
    context_->connDelayCloseTime = 0;
    const int32_t MICROSECOND_PER_SECOND = 1000000L;
    if (context_->connSessionType != CONN_SESSION_TYPE_HML) {
        context_->connDelayCloseTime = DEFAULT_DELAY_CLOSE_TIME_US;
    }
    if (context_->connDelayCloseTime == 0) {
        context_->connDelayCloseTime = HML_SESSION_TIMEOUT * MICROSECOND_PER_SECOND;
    }
    if (jsonObject[PARAM_CLOSE_SESSION_DELAY_SECONDS].IsString()) {
        std::string delaySecondsStr = jsonObject[PARAM_CLOSE_SESSION_DELAY_SECONDS].Get<std::string>();
        context_->connDelayCloseTime = GetCloseSessionDelaySeconds(delaySecondsStr) * MICROSECOND_PER_SECOND;
    }
}
//LCOV_EXCL_STOP
}  // namespace DistributedHardware
}  // namespace OHOS