/*
 * Copyright (C) 2022-2026 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 "accessible_ability_channel.h"
#include "accessible_ability_manager_service.h"
#include "accessibility_window_connection.h"
#include "accessibility_window_manager.h"
#include "accessible_ability_connection.h"
#include "display_manager.h"
#include "hilog_wrapper.h"
#include <cinttypes>
#include <unordered_map>
#ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
#include "accessibility_power_manager.h"
#endif
#include "utils.h"

namespace OHOS {
namespace Accessibility {
namespace {
    constexpr int32_t WINDOW_ID_INVALID = -1;
    constexpr int64_t ELEMENT_ID_INVALID = -1;
    const int32_t LONG_PRESS_EVENT_INTERVAL = 550;
    const int32_t DOUBLE_CLICK_EVENT_INTERVAL = 100;
    MMI::InputManager* inputManager_ = MMI::InputManager::GetInstance();
    std::map<int32_t, std::pair<bool, std::pair<int32_t, int32_t>>> accessibleKeyCodeTable = {
        {ActionType::ACCESSIBILITY_ACTION_HOME,
            {false, {MMI::KeyEvent::KEYCODE_META_LEFT, MMI::KeyEvent::KEYCODE_D}}},
        {ActionType::ACCESSIBILITY_ACTION_RECENTTASK,
            {false, {MMI::KeyEvent::KEYCODE_META_LEFT, MMI::KeyEvent::KEYCODE_TAB}}},
        {ActionType::ACCESSIBILITY_ACTION_BACK,
            {true, {MMI::KeyEvent::KEYCODE_BACK, MMI::KeyEvent::KEYCODE_BACK}}},
        {ActionType::ACCESSIBILITY_ACTION_NOTIFICATIONCENTER,
            {true, {MMI::KeyEvent::KEYCODE_CALL_NOTIFICATION_CENTER, MMI::KeyEvent::KEYCODE_CALL_NOTIFICATION_CENTER}}},
        {ActionType::ACCESSIBILITY_ACTION_CONTROLCENTER,
            {true, {MMI::KeyEvent::KEYCODE_CALL_CONTROL_CENTER, MMI::KeyEvent::KEYCODE_CALL_CONTROL_CENTER}}}};

    InjectActionType StringToInjectAction(const std::string& injectActionType)
    {
        static const std::unordered_map<std::string, InjectActionType> actionMap = {
            {"click", INJECT_ACTION_TYPE_CLICK},
            {"doubleClick", INJECT_ACTION_TYPE_DOUBLE_CLICK},
            {"longClick", INJECT_ACTION_TYPE_LONG_CLICK},
            {"1", INJECT_ACTION_TYPE_CLICK},
            {"2", INJECT_ACTION_TYPE_DOUBLE_CLICK},
            {"3", INJECT_ACTION_TYPE_LONG_CLICK}
        };
 
        auto it = actionMap.find(injectActionType);
        if (it != actionMap.end()) {
            return it->second;
        }
        return INJECT_ACTION_TYPE_INVALID;
    }
} // namespace

AccessibleAbilityChannel::AccessibleAbilityChannel(
    const int32_t accountId, const std::string &clientName, const wptr<AccessibilityAccountData> &accountData)
    : clientName_(clientName), accountId_(accountId), accountData_(accountData)
{
    eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
        Singleton<AccessibleAbilityManagerService>::GetInstance().GetChannelRunner());
}

RetError AccessibleAbilityChannel::SearchElementInfoByAccessibilityId(const ElementBasicInfo elementBasicInfo,
    const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback,
    const int32_t mode, bool isFilter, bool systemApi)
{
    int32_t treeId = elementBasicInfo.treeId;
    int32_t windowId = elementBasicInfo.windowId;
    int64_t elementId = elementBasicInfo.elementId;
    HILOG_DEBUG("elementId:%{public}" PRId64 " winId: %{public}d treeId: %{public}d", elementId, windowId, treeId);
    if (systemApi && !Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        HILOG_WARN("SearchElementInfoByAccessibilityId permission denied.");
        return RET_ERR_NO_PERMISSION;
    }
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();

    if (eventHandler_ == nullptr || callback == nullptr) {
        HILOG_ERROR("eventHandler_ exist: %{public}d, callback exist: %{public}d.", eventHandler_ != nullptr,
            callback != nullptr);
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, windowId, elementId, treeId, requestId,
        callback, mode, isFilter]() {
        HILOG_DEBUG("search element accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID, clientName,
            elementOperator, treeId);
        if (ret != RET_OK || !CheckWinFromAwm(windowId, ret)) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
            syncPromise->set_value(ret);
            if (elementOperator != nullptr) {
                HILOG_INFO("before elementOperator release, refCount is [%{public}d]",
                    elementOperator->GetSptrRefCount());
            }
            return;
        }

        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            return;
        }
        int64_t realElementId = accountData->GetWindowManager().GetSceneBoardElementId(windowId, elementId);
        accountData->GetElementOperatorManager().AddRequestId(windowId, treeId, requestId, callback);
        ret = elementOperator->SearchElementInfoByAccessibilityId(realElementId, requestId,
            callback, mode, isFilter);
        if (ret != RET_OK) {
            HILOG_ERROR("SearchElementInfoByAccessibilityId IPC Failed.");
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
            syncPromise->set_value(ret);
            return;
        }
        HILOG_DEBUG("AccessibleAbilityChannel::SearchElementInfoByAccessibilityId successfully");
        syncPromise->set_value(RET_OK);
        }, "SearchElementInfoByAccessibilityId");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SearchElementInfoByAccessibilityId result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::SearchDefaultFocusedByWindowId(const ElementBasicInfo elementBasicInfo,
    const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback,
    const int32_t mode, bool isFilter)
{
    int32_t windowId = elementBasicInfo.windowId;
    int64_t elementId = elementBasicInfo.elementId;
    int32_t treeId = elementBasicInfo.treeId;
    HILOG_DEBUG("elementId:%{public}" PRId64 " winId: %{public}d treeId: %{public}d", elementId, windowId, treeId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
 
    if (eventHandler_ == nullptr || callback == nullptr) {
        HILOG_ERROR("eventHandler_ exist: %{public}d, callback exist: %{public}d.", eventHandler_ != nullptr,
            callback != nullptr);
        return RET_ERR_NULLPTR;
    }
 
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, windowId, elementId, treeId, requestId,
        callback, mode, isFilter]() {
        HILOG_DEBUG("search element accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID, clientName,
            elementOperator, treeId);
        if (ret != RET_OK || !CheckWinFromAwm(windowId, ret)) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchDefaultFocusByWindowIdResult(infos, requestId);
            syncPromise->set_value(ret);
            return;
        }
 
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            syncPromise->set_value(RET_ERR_FAILED);
            return;
        }
        if (windowId == SCENE_BOARD_WINDOW_ID && accountData->GetWindowManager().IsInnerWindowRootElement(elementId)) {
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchDefaultFocusByWindowIdResult(infos, requestId);
        } else {
            accountData->GetElementOperatorManager().AddRequestId(windowId, treeId, requestId, callback);
            elementOperator->SearchDefaultFocusedByWindowId(windowId, requestId, callback, mode, isFilter);
            HILOG_DEBUG("AccessibleAbilityChannel::SearchElementInfoByAccessibilityId successfully");
        }
        syncPromise->set_value(RET_OK);
        }, "SearchElementInfoByAccessibilityId");
 
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SearchElementInfoByAccessibilityId result");
        return RET_ERR_TIME_OUT;
    }
    return RET_OK;
}

RetError AccessibleAbilityChannel::SearchElementInfosByText(const int32_t accessibilityWindowId,
    const int64_t elementId, const std::string &text, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback, bool systemApi)
{
    HILOG_DEBUG("SearchElementInfosByText :channel SearchElementInfo elementId: %{public}" PRId64 " winId: %{public}d",
        elementId, accessibilityWindowId);
    if (systemApi && !Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        return RET_ERR_NO_PERMISSION;
    }
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
    if (callback == nullptr) {
        HILOG_ERROR("callback is nullptr.");
        return RET_ERR_NULLPTR;
    }
    int32_t treeId = Utils::GetTreeIdBySplitElementId(elementId);
    HILOG_DEBUG("SearchElementInfosByText :channel SearchElementInfo treeId: %{public}d", treeId);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, accessibilityWindowId, elementId, treeId, text,
        requestId, callback]() {
        HILOG_DEBUG("accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, accessibilityWindowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", accessibilityWindowId);
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
            syncPromise->set_value(ret);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            syncPromise->set_value(RET_ERR_FAILED);
            return;
        }
        int64_t realElementId =
            accountData->GetWindowManager().GetSceneBoardElementId(accessibilityWindowId, elementId);
        accountData->GetElementOperatorManager().AddRequestId(accessibilityWindowId, treeId, requestId, callback);
        elementOperator->SearchElementInfosByText(realElementId, text, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "SearchElementInfosByText");
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SearchElementInfosByText result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::FindFocusedElementInfo(const int32_t accessibilityWindowId,
    const int64_t elementId, const int32_t focusType, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback, bool systemApi)
{
    HILOG_DEBUG("channel FindFocusedElementInfo elementId: %{public}" PRId64 " winId: %{public}d",
        elementId, accessibilityWindowId);
    if (systemApi && !Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        return RET_ERR_NO_PERMISSION;
    }
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
    if (callback == nullptr) {
        HILOG_ERROR("callback is nullptr.");
        return RET_ERR_NULLPTR;
    }
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t treeId = Utils::GetTreeIdBySplitElementId(elementId);
    HILOG_DEBUG("FindFocusedElementInfo :channel FindFocusedElementInfo treeId: %{public}d", treeId);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, accessibilityWindowId, elementId, treeId,
        focusType, requestId, callback]() {
        HILOG_DEBUG("accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, accessibilityWindowId, focusType,
            clientName, elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", accessibilityWindowId);
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
            syncPromise->set_value(ret);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            syncPromise->set_value(RET_ERR_FAILED);
            return;
        }
        int64_t realElementId = ROOT_NODE_ID;
        if (treeId <= 0) {
            realElementId = accountData->GetWindowManager().GetSceneBoardElementId(accessibilityWindowId, elementId);
        }
        accountData->GetElementOperatorManager().AddRequestId(accessibilityWindowId, treeId, requestId, callback);
        elementOperator->FindFocusedElementInfo(realElementId, focusType, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "FindFocusedElementInfo");
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait FindFocusedElementInfo result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::FocusMoveSearch(const int32_t accessibilityWindowId, const int64_t elementId,
    const int32_t direction, const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback,
    bool systemApi)
{
    HILOG_DEBUG("FocusMoveSearch :channel FocusMoveSearch elementId: %{public}" PRId64 " winId: %{public}d",
        elementId, accessibilityWindowId);
    if (systemApi && !Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        return RET_ERR_NO_PERMISSION;
    }
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
    if (callback == nullptr) {
        HILOG_ERROR("callback is nullptr.");
        return RET_ERR_NULLPTR;
    }
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t treeId = Utils::GetTreeIdBySplitElementId(elementId);
    HILOG_DEBUG("FocusMoveSearch :channel FocusMoveSearch treeId: %{public}d", treeId);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, accessibilityWindowId,
        elementId, treeId, direction, requestId, callback]() {
        HILOG_DEBUG("accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, accessibilityWindowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", accessibilityWindowId);
            std::vector<AccessibilityElementInfo> infos = {};
            callback->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
            syncPromise->set_value(ret);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            syncPromise->set_value(RET_ERR_FAILED);
            HILOG_ERROR("accountData is nullptr");
            return;
        }
        int64_t realElementId =
            accountData->GetWindowManager().GetSceneBoardElementId(accessibilityWindowId, elementId);
        accountData->GetElementOperatorManager().AddRequestId(accessibilityWindowId, treeId, requestId, callback);
        elementOperator->FocusMoveSearch(realElementId, direction, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "FocusMoveSearch");
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait FocusMoveSearch result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

void AccessibleAbilityChannel::SetKeyCodeToMmi(std::shared_ptr<MMI::KeyEvent>& keyEvent, const bool isPress,
    const int32_t keyCode)
{
    HILOG_DEBUG();
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (keyEvent == nullptr) {
        HILOG_ERROR("KeyEvent is nullptr");
        return;
    }
    MMI::KeyEvent::KeyItem item;
    item.SetPressed(isPress);
    item.SetKeyCode(keyCode);
    keyEvent->AddKeyItem(item);
    keyEvent->SetKeyCode(keyCode);
}

RetError AccessibleAbilityChannel::TransmitActionToMmi(const int32_t action)
{
    HILOG_DEBUG("The action is %{public}d", action);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    std::shared_ptr<MMI::KeyEvent> keyEventUp = MMI::KeyEvent::Create();
    std::shared_ptr<MMI::KeyEvent> keyEventDown = MMI::KeyEvent::Create();
    if (keyEventUp == nullptr || keyEventDown == nullptr) {
        HILOG_ERROR("KeyEvent is nullptr");
        return RET_ERR_NULLPTR;
    }

    if (!inputManager_) {
        HILOG_ERROR("inputManager_ is nullptr");
        return RET_ERR_NULLPTR;
    }
    
    HILOG_INFO("Transmit keycode to MMI");

    if (accessibleKeyCodeTable.find(action) == accessibleKeyCodeTable.end()) {
        HILOG_ERROR("Unrecognized action!");
        return RET_ERR_INVALID_PARAM;
    }

    if (accessibleKeyCodeTable.at(action).first) {
        SetKeyCodeToMmi(keyEventDown, true, accessibleKeyCodeTable.at(action).second.first);
        SetKeyCodeToMmi(keyEventUp, false, accessibleKeyCodeTable.at(action).second.first);
    } else {
        SetKeyCodeToMmi(keyEventDown, true, accessibleKeyCodeTable.at(action).second.first);
        SetKeyCodeToMmi(keyEventUp, false, accessibleKeyCodeTable.at(action).second.first);
        SetKeyCodeToMmi(keyEventDown, true, accessibleKeyCodeTable.at(action).second.second);
    }
    keyEventDown->SetKeyAction(MMI::KeyEvent::KEY_ACTION_DOWN);
    keyEventUp->SetKeyAction(MMI::KeyEvent::KEY_ACTION_UP);
    inputManager_->SimulateInputEvent(keyEventDown);
    inputManager_->SimulateInputEvent(keyEventUp);

    return RET_OK;
}

RetError AccessibleAbilityChannel::EnableScreenCurtain(bool isEnable)
{
    HILOG_DEBUG();
    auto& aams = Singleton<AccessibleAbilityManagerService>::GetInstance();
    aams.PostDelayUnloadTask();
    return aams.SetCurtainScreenUsingStatus(isEnable);
}

RetError AccessibleAbilityChannel::HoldRunningLock()
{
    HILOG_DEBUG();
    if (!Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        HILOG_WARN("HoldRunningLock permission denied.");
        return RET_ERR_NO_PERMISSION;
    }
#ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
    std::string bundleName = "";
    if (!Utils::GetBundleNameByCallingUid(bundleName)) {
        return RET_ERR_FAILED;
    }
    if (!Singleton<AccessibilityPowerManager>::GetInstance().HoldRunningLock(bundleName)) {
        HILOG_ERROR("Failed to hold running lock.");
        return RET_ERR_FAILED;
    }
#endif
    return RET_OK;
}

RetError AccessibleAbilityChannel::UnholdRunningLock()
{
    HILOG_DEBUG();
    if (!Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        HILOG_WARN("UnholdRunningLock permission denied.");
        return RET_ERR_NO_PERMISSION;
    }
#ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
    std::string bundleName = "";
    if (!Utils::GetBundleNameByCallingUid(bundleName)) {
        return RET_ERR_FAILED;
    }
    auto &powerManager = Singleton<AccessibilityPowerManager>::GetInstance();
    if (!powerManager.UnholdRunningLock(bundleName)) {
        HILOG_ERROR("Failed to unhold running lock.");
        return RET_ERR_FAILED;
    }
#endif
    return RET_OK;
}

RetError AccessibleAbilityChannel::ExecuteAction(const int32_t accessibilityWindowId, const int64_t elementId,
    const int32_t action, const std::map<std::string, std::string> &actionArguments, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback, const Rect &rect)
{
    HILOG_DEBUG("ExecuteAction elementId:%{public}" PRId64 " winId:%{public}d, action:%{public}d, requestId:%{public}d",
        elementId, accessibilityWindowId, action, requestId);
    if (actionArguments.find("sysapi_check_perm") != actionArguments.end()) {
        if (!Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
            OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
            HILOG_WARN("system api permission denied.");
            return RET_ERR_NO_PERMISSION;
        }
    }

    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr || callback == nullptr) {
        HILOG_ERROR("eventHandler_ exist: %{public}d, callback exist: %{public}d.", eventHandler_ != nullptr,
            callback != nullptr);
        return RET_ERR_NULLPTR;
    }

    if (accessibleKeyCodeTable.find(action) != accessibleKeyCodeTable.end()) {
        RetError ret = TransmitActionToMmi(action);
        if (ret != RET_OK) {
            HILOG_ERROR("Transmit Action To Mmi failed!");
            callback->SetExecuteActionResult(false, requestId);
            return RET_ERR_FAILED;
        }
        callback->SetExecuteActionResult(true, requestId);
        return RET_OK;
    }

    if (action == ActionType::ACCESSIBILITY_ACTION_INJECT_ACTION) {
        RetError ret = HandleInjectAction(actionArguments, rect);
        if (ret != RET_OK) {
            HILOG_ERROR("Handle Inject Click failed!");
            callback->SetExecuteActionResult(false, requestId);
            return RET_ERR_FAILED;
        }
        callback->SetExecuteActionResult(true, requestId);
        return RET_OK;
    }
    return ExecuteActionAsync(accessibilityWindowId, elementId, action, actionArguments, requestId, callback);
}

RetError AccessibleAbilityChannel::HandleInjectAction(const std::map<std::string, std::string> &actionArguments,
    const Rect &rect)
{
    HILOG_DEBUG();
    auto it = actionArguments.find("injectActionType");
    if (it == actionArguments.end()) {
        HILOG_ERROR("HandleInjectAction injectActionType not found in actionArguments");
        return RET_ERR_INVALID_PARAM;
    }
    std::string clickTypeStr = it->second;
    HILOG_INFO("HandleInjectAction clickType: %{public}s", clickTypeStr.c_str());

    InjectActionType injectActionType = StringToInjectAction(clickTypeStr);
    if (injectActionType == INJECT_ACTION_TYPE_INVALID) {
        HILOG_ERROR("HandleInjectAction invalid clickType: %{public}s", clickTypeStr.c_str());
        return RET_ERR_INVALID_PARAM;
    }

    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        HILOG_ERROR("accountData is nullptr");
        return RET_ERR_FAILED;
    }

    int32_t xPos = 0;
    int32_t yPos = 0;
    int32_t windowId = accountData->GetWindowManager().GetActiveWindowId();
    if (!accountData->GetElementOperatorManager().CalculateClickPosition(rect, xPos, yPos, windowId)) {
        HILOG_ERROR("CalculateClickPosition failed, element is out of window bounds");
        return RET_ERR_FAILED;
    }

    InjectEventToInput(xPos, yPos, injectActionType);
    return RET_OK;
}

void AccessibleAbilityChannel::InjectEventToInput(int32_t xPos, int32_t yPos, InjectActionType injectActionType)
{
    HILOG_INFO("InjectEventToInput injectActionType: %{public}d, position: [%{public}d, %{public}d]",
        injectActionType, xPos, yPos);

    if (xPos < 0 || yPos < 0) {
        HILOG_ERROR("InjectEventToInput invalid position: [%{public}d, %{public}d]", xPos, yPos);
        return;
    }

    auto injectTouchEvent = [](int32_t x, int32_t y, int32_t action) {
        std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create();
        pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
        pointerEvent->SetPointerAction(action);
        pointerEvent->AddFlag(MMI::InputEvent::EVENT_FLAG_ACCESSIBILITY);
        pointerEvent->AddFlag(MMI::InputEvent::EVENT_FLAG_NO_INTERCEPT);
        MMI::PointerEvent::PointerItem item;
        item.SetDisplayX(x);
        item.SetDisplayY(y);
        item.SetRawDisplayX(x);
        item.SetRawDisplayY(y);
        item.SetPointerId(0);
        pointerEvent->AddPointerItem(item);
        pointerEvent->SetPointerId(0);
        MMI::InputManager::GetInstance()->SimulateInputEvent(pointerEvent);
    };

    if (injectActionType == INJECT_ACTION_TYPE_CLICK) {
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_DOWN);
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_UP);
    } else if (injectActionType == INJECT_ACTION_TYPE_DOUBLE_CLICK) {
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_DOWN);
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_UP);
        std::this_thread::sleep_for(std::chrono::milliseconds(DOUBLE_CLICK_EVENT_INTERVAL));
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_DOWN);
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_UP);
    } else if (injectActionType == INJECT_ACTION_TYPE_LONG_CLICK) {
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_DOWN);
        std::this_thread::sleep_for(std::chrono::milliseconds(LONG_PRESS_EVENT_INTERVAL));
        injectTouchEvent(xPos, yPos, MMI::PointerEvent::POINTER_ACTION_UP);
    }
}

RetError AccessibleAbilityChannel::ExecuteActionAsync(const int32_t accessibilityWindowId, const int64_t elementId,
    const int32_t action, const std::map<std::string, std::string> &actionArguments, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    SetFocusWindowIdAndElementId(accessibilityWindowId, elementId, action);
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t treeId = Utils::GetTreeIdBySplitElementId(elementId);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, accessibilityWindowId, elementId, treeId, action,
        actionArguments, requestId, callback]() {
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, accessibilityWindowId, FOCUS_TYPE_INVALID, clientName,
            elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", accessibilityWindowId);
            syncPromise->set_value(ret);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            syncPromise->set_value(RET_ERR_FAILED);
            return;
        }
        int32_t realElementId =
            accountData->GetWindowManager().GetSceneBoardElementId(accessibilityWindowId, elementId);
        accountData->GetElementOperatorManager().AddRequestId(accessibilityWindowId, treeId, requestId, callback);
        elementOperator->ExecuteAction(realElementId, action, actionArguments, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "ExecuteAction");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_1000MS));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait ExecuteAction result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

void AccessibleAbilityChannel::SetFocusWindowIdAndElementId(const int32_t accessibilityWindowId,
    const int64_t elementId, const int32_t action)
{
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        return;
    }
    auto& awm = Singleton<AccessibleAbilityManagerService>::GetInstance();
    if ((action == ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS)) {
        accountData->GetElementOperatorManager().SetFocusWindowId(accessibilityWindowId);
        accountData->GetElementOperatorManager().SetFocusElementId(elementId);
    } else if (action == ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
        accountData->GetElementOperatorManager().SetFocusWindowId(WINDOW_ID_INVALID);
        accountData->GetElementOperatorManager().SetFocusElementId(ELEMENT_ID_INVALID);
    }
}

RetError AccessibleAbilityChannel::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
{
    HILOG_DEBUG("windowId:%{public}d", windowId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
 
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    std::shared_ptr<AccessibilityWindowInfo> tmpWindowInfo = std::make_shared<AccessibilityWindowInfo>(windowInfo);
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, windowId, tmpWindowInfo, syncPromise]() {
        HILOG_DEBUG("windowId:%{public}d", windowId);
        sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
        if (!clientConnection) {
            HILOG_ERROR("There is no client connection");
            syncPromise->set_value(RET_ERR_NO_CONNECTION);
            return;
        }
        if (!(clientConnection->GetAbilityInfo().GetCapabilityValues() & Capability::CAPABILITY_RETRIEVE)) {
            HILOG_ERROR("AccessibleAbilityChannel::GetWindow failed: no capability");
            syncPromise->set_value(RET_ERR_NO_CAPABILITY);
            return;
        }

        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            syncPromise->set_value(RET_ERR_NULLPTR);
            return;
        }

        if (accountData->GetWindowManager().GetAccessibilityWindow(windowId, *tmpWindowInfo)) {
            syncPromise->set_value(RET_OK);
        } else {
            syncPromise->set_value(RET_ERR_NO_WINDOW_CONNECTION);
        }
        }, "GetWindow");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait GetWindow result");
        return RET_ERR_TIME_OUT;
    }

    windowInfo = *tmpWindowInfo;
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::GetWindows(std::vector<AccessibilityWindowInfo> &windows, bool systemApi)
{
    HILOG_DEBUG();
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    uint64_t displayId = Singleton<ExtendManagerServiceProxy>::GetInstance().GetDefaultDisplayId();
    return GetWindows(displayId, windows, systemApi);
}

RetError AccessibleAbilityChannel::GetWindowsByDisplayId(const uint64_t displayId,
    std::vector<AccessibilityWindowInfo> &windows, bool systemApi)
{
    HILOG_DEBUG();
    return GetWindows(displayId, windows, systemApi);
}

RetError AccessibleAbilityChannel::GetWindows(uint64_t displayId, std::vector<AccessibilityWindowInfo> &windows,
    bool systemApi) const
{
    if (systemApi && !Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        return RET_ERR_NO_PERMISSION;
    }
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    auto tmpWindows = std::make_shared<std::vector<AccessibilityWindowInfo>>(windows);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, displayId, tmpWindows, syncPromise]() {
        HILOG_DEBUG();
        sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
        if (!clientConnection) {
            HILOG_ERROR("There is no client connection");
            syncPromise->set_value(RET_ERR_NO_CONNECTION);
            return;
        }
        if (!(clientConnection->GetAbilityInfo().GetCapabilityValues() & Capability::CAPABILITY_RETRIEVE)) {
            HILOG_ERROR("GetWindows failed: no capability");
            syncPromise->set_value(RET_ERR_NO_CAPABILITY);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            syncPromise->set_value(RET_ERR_FAILED);
            return;
        }
        std::vector<AccessibilityWindowInfo> windowInfos = accountData->GetWindowManager().GetAccessibilityWindows();
#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
        for (auto &window : windowInfos) {
            if (window.GetDisplayId() == displayId) {
                tmpWindows->emplace_back(window);
            }
        }
#else
        for (auto &window : windowInfos) {
            tmpWindows->emplace_back(window);
        }
#endif
        syncPromise->set_value(RET_OK);
        }, "GetWindows");
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait GetWindows result");
        return RET_ERR_TIME_OUT;
    }
    windows = *tmpWindows;
    return syncFuture.get();
}

void AccessibleAbilityChannel::SetOnKeyPressEventResult(const bool handled, const int32_t sequence)
{
    HILOG_DEBUG();
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    eventHandler_->PostTask([this, accountId, clientName, handled, sequence]() {
        sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
        if (!clientConnection) {
            HILOG_ERROR("There is no client connection");
            return;
        }
        Singleton<ExtendManagerServiceProxy>::GetInstance().SetServiceOnKeyEventResult(
            clientConnection->GetChannelId(), handled, sequence);
        }, "SetOnKeyPressEventResult");
}

RetError AccessibleAbilityChannel::GetCursorPosition(const int32_t accessibilityWindowId, const int64_t elementId,
    const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    HILOG_DEBUG("GetCursorPosition :channel GetCursorPosition elementId: %{public}" PRId64 " winId: %{public}d",
        elementId, accessibilityWindowId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t treeId = Utils::GetTreeIdBySplitElementId(elementId);
    HILOG_DEBUG("GetCursorPosition :channel GetCursorPosition treeId: %{public}d", treeId);
    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, accessibilityWindowId, elementId, treeId,
        requestId, callback]() {
        HILOG_DEBUG("accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, accessibilityWindowId, FOCUS_TYPE_INVALID, clientName,
            elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", accessibilityWindowId);
            syncPromise->set_value(ret);
            return;
        }
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            return;
        }
        int64_t realElementId =
            accountData->GetWindowManager().GetSceneBoardElementId(accessibilityWindowId, elementId);
        accountData->GetElementOperatorManager().AddRequestId(accessibilityWindowId, treeId, requestId, callback);
        elementOperator->GetCursorPosition(realElementId, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "GetCursorPosition");
    
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait GetCursorPosition result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::SendSimulateGesture(
    const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
{
    HILOG_INFO();
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr");
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, gesturePath, syncPromise]() {
        HILOG_DEBUG();
        sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
        if (!clientConnection) {
            HILOG_ERROR("There is no client connection");
            syncPromise->set_value(RET_ERR_NO_CONNECTION);
            return;
        }

        if (!(clientConnection->GetAbilityInfo().GetCapabilityValues() & Capability::CAPABILITY_GESTURE)) {
            HILOG_ERROR("AccessibleAbilityChannel::SendSimulateGesture failed: no capability");
            syncPromise->set_value(RET_ERR_NO_CAPABILITY);
            return;
        }

        if (Singleton<ExtendManagerServiceProxy>::GetInstance().LoadExtProxy()) {
            RetError ret = Singleton<ExtendManagerServiceProxy>::GetInstance().InjectEvents(gesturePath);
            if (ret != RET_OK) {
                syncPromise->set_value(RET_ERR_NO_INJECTOR);
                return;
            }
        }
        syncPromise->set_value(RET_OK);
        }, "SendSimulateGesture");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SendSimulateGesture result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
{
    HILOG_DEBUG();
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_== nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr");
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, targetBundleNames, syncPromise]() {
        HILOG_DEBUG();
        sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
        if (!clientConnection) {
            HILOG_ERROR("There is no client connection");
            syncPromise->set_value(RET_ERR_NO_CONNECTION);
            return;
        }

        clientConnection->SetAbilityInfoTargetBundleName(targetBundleNames);
        syncPromise->set_value(RET_OK);
        }, "SetTargetBundleName");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SetTargetBundleName result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}
sptr<AccessibleAbilityConnection> AccessibleAbilityChannel::GetConnection(
    int32_t accountId, const std::string &clientName) const
{
    HILOG_DEBUG();
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (accountData == nullptr) {
        HILOG_ERROR("accountData is nullptr");
        return nullptr;
    }

    HILOG_DEBUG("accountId[%{public}d] clientName[%{public}s]", accountId, clientName.c_str());
    return accountData->GetAccessibleAbilityConnection(clientName);
}

RetError AccessibleAbilityChannel::GetElementOperator(
    int32_t accountId, int32_t windowId, int32_t focusType, const std::string &clientName,
    sptr<IAccessibilityElementOperator> &elementOperator, const int32_t treeId)
{
    HILOG_DEBUG();
    elementOperator = nullptr;
    sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId, clientName);
    if (!clientConnection) {
        HILOG_ERROR("There is no client connection");
        return RET_ERR_NO_CONNECTION;
    }
    if (!(clientConnection->GetAbilityInfo().GetCapabilityValues() & Capability::CAPABILITY_RETRIEVE)) {
        HILOG_ERROR("the client has no retieve capability");
        return RET_ERR_NO_CAPABILITY;
    }

    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        HILOG_ERROR("accountData is nullptr");
        return RET_ERR_NULLPTR;
    }
    auto [realId, displayId] = accountData->GetWindowManager().ConvertToRealWindowId(windowId, focusType);
    sptr<AccessibilityWindowConnection> connection =  accountData->GetAccessibilityWindowConnection(realId);
    if (connection == nullptr) {
        HILOG_ERROR("windowId[%{public}d] has no connection", realId);
        return RET_ERR_NO_WINDOW_CONNECTION;
    }

    bool isAnco = connection->IsAnco();
    bool useBroker = connection->GetUseBrokerFlag();
    bool hasMultipleProxies = (connection->GetCardProxySize() > 1);
    
    if (!useBroker && treeId > 0) {
        elementOperator = connection->GetCardProxy(treeId);
    } else if (isAnco && useBroker && treeId > 0
        && connection->GetCardProxy(treeId)) {
        elementOperator = connection->GetCardProxy(treeId);
    } else if (isAnco && useBroker && treeId == 0
        && hasMultipleProxies && connection->GetCardProxy(treeId)) {
        elementOperator = connection->GetCardProxy(treeId);
    } else {
        elementOperator = connection->GetProxy(displayId);
    }
    if (!elementOperator) {
        HILOG_ERROR("The proxy of window connection is nullptr");
        return RET_ERR_NULLPTR;
    }
    return RET_OK;
}

bool AccessibleAbilityChannel::CheckWinFromAwm(const int32_t windowId, const int32_t getElementOperatorResult)
{
    HILOG_DEBUG("CheckWinFromAwm window: %{public}d, ConnectResult: [%{public}d]", windowId, getElementOperatorResult);
    if (windowId == SCENE_BOARD_WINDOW_ID && getElementOperatorResult == RET_OK) {
        return true;
    }
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        return false;
    }
    std::vector<AccessibilityWindowInfo> windows = accountData->GetWindowManager().GetAccessibilityWindows();
    if (!windows.empty()) {
        for (const auto& window: windows) {
            if (windowId == window.GetWindowId()) {
                return true;
            }
        }
    }
    return false;
}

RetError AccessibleAbilityChannel::SetIsRegisterDisconnectCallback(bool isRegister)
{
    HILOG_INFO();
    if (!Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        HILOG_WARN("SetIsRegisterDisconnectCallback permission denied.");
        return RET_ERR_NO_PERMISSION;
    }
    sptr<AccessibleAbilityConnection> clientConnection = GetConnection(accountId_, clientName_);
    if (clientConnection == nullptr) {
        HILOG_ERROR("GetConnection failed, clientName: %{public}s", clientName_.c_str());
        return RET_ERR_NULLPTR;
    }
    clientConnection->SetIsRegisterDisconnectCallback(isRegister);
    return RET_OK;
}

RetError AccessibleAbilityChannel::NotifyDisconnect()
{
    HILOG_INFO();
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (accountData == nullptr) {
        HILOG_ERROR("accountData is nullptr");
        return RET_ERR_NULLPTR;
    }
    sptr<AccessibleAbilityConnection> clientConnection =
        accountData_->GetAccessibleAbilityManager().GetWaitDisConnectAbility(clientName_);
    if (clientConnection == nullptr) {
        HILOG_ERROR("GetConnection failed, clientName: %{public}s", clientName_.c_str());
        return RET_ERR_NULLPTR;
    }
    accountData_->GetAccessibleAbilityManager().RemoveWaitDisconnectAbility(clientName_);
    clientConnection->NotifyDisconnect();
    return RET_OK;
}

void AccessibleAbilityChannel::SearchElementInfoBySpecificProperty(const ElementBasicInfo elementBasicInfo,
    const SpecificPropertyParam& param, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    int32_t treeId = elementBasicInfo.treeId;
    int32_t windowId = elementBasicInfo.windowId;
    int64_t elementId = elementBasicInfo.elementId;
    HILOG_DEBUG("elementId:%{public}" PRId64 " winId: %{public}d treeId: %{public}d "
        "propertyTarget:%{public}s propertyType:%{public}u",
        elementId, windowId, treeId, param.propertyTarget.c_str(), static_cast<uint32_t>(param.propertyType));
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();

    if (eventHandler_ == nullptr || callback == nullptr) {
        HILOG_ERROR("eventHandler_ exist: %{public}d, callback exist: %{public}d.", eventHandler_ != nullptr,
            callback != nullptr);
        return;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, windowId, elementId, treeId, requestId,
        callback, param]() {
        HILOG_DEBUG("search element accountId[%{public}d], name[%{public}s]", accountId, clientName.c_str());
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID, clientName,
            elementOperator, treeId);
        if (ret != RET_OK || !CheckWinFromAwm(windowId, ret)) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            std::list<AccessibilityElementInfo> infos = {};
            std::list<AccessibilityElementInfo> treeInfos = {};
            callback->SetSearchElementInfoBySpecificPropertyResult(infos, treeInfos, requestId);
            syncPromise->set_value(ret);
            return;
        }

        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            return;
        }
        if (windowId == SCENE_BOARD_WINDOW_ID && accountData->GetWindowManager().IsInnerWindowRootElement(elementId)) {
            std::list<AccessibilityElementInfo> infos = {};
            std::list<AccessibilityElementInfo> treeInfos = {};
            callback->SetSearchElementInfoBySpecificPropertyResult(infos, treeInfos, requestId);
            HILOG_DEBUG("IsInnerWindowRootElement elementId: %{public}" PRId64 "", elementId);
        } else {
            int64_t realElementId = accountData->GetWindowManager().GetSceneBoardElementId(windowId, elementId);
            accountData->GetElementOperatorManager().AddRequestId(windowId, treeId, requestId, callback);
            elementOperator->SearchElementInfoBySpecificProperty(realElementId, param, requestId, callback);
            HILOG_DEBUG("AccessibleAbilityChannel::SearchElementInfosBySpecificProperty successfully");
        }
        syncPromise->set_value(RET_OK);
        }, "SearchElementInfosBySpecificProperty");
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        HILOG_ERROR("accountData is nullptr");
        return;
    }
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        accountData->GetElementOperatorManager().RemoveRequestId(requestId);
        HILOG_ERROR("Failed to wait SearchElementInfosBySpecificProperty result");
        return;
    }
}

RetError AccessibleAbilityChannel::ConfigureEvents(const std::vector<uint32_t> needEvents)
{
    HILOG_INFO();
    sptr<AccessibilityAccountData> accountData = accountData_.promote();
    if (!accountData) {
        return RET_ERR_FAILED;
    }
    RetError ret = accountData->ConfigureEvents(needEvents);
    if (ret != RET_OK) {
        HILOG_ERROR("Configure Events failed!");
        return RET_ERR_FAILED;
    }
    return RET_OK;
}

RetError AccessibleAbilityChannel::FocusMoveSearchWithCondition(const AccessibilityElementInfo &elementInfo,
    const AccessibilityFocusMoveParam &param,  const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback, int32_t windowId)
{
    HILOG_DEBUG("requestId: %{public}d, windowId: %{public}d", requestId, windowId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr || callback == nullptr) {
        HILOG_ERROR("eventHandler_ exist: %{public}d, callback exist: %{public}d.", eventHandler_ != nullptr,
            callback != nullptr);
        return RET_ERR_NULLPTR;
    }

    if (!Singleton<AccessibleAbilityManagerService>::GetInstance().CheckPermission(
        OHOS_PERMISSION_ACCESSIBILITY_EXTENSION_ABILITY)) {
        HILOG_WARN("SearchElementInfoByAccessibilityId permission denied.");
        return RET_ERR_NO_PERMISSION;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    eventHandler_->PostTask([this, accountId, clientName, syncPromise, windowId, elementInfo,
        requestId, callback, param]() {
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        int32_t treeId = elementInfo.GetBelongTreeId();
        sptr<AccessibilityAccountData> accountData = accountData_.promote();
        if (!accountData) {
            HILOG_ERROR("accountData is nullptr");
            return;
        }
        if (param.detectParent) {
            int64_t parentId = -1;
            accountData->GetElementOperatorManager().GetRootParentId(windowId, treeId, parentId);
            const_cast<AccessibilityFocusMoveParam&>(param).SetParentId(parentId);
            treeId = Utils::GetTreeIdBySplitElementId(parentId);
            HILOG_DEBUG("requestId: %{public}d, treeId: %{public}d", requestId, treeId);
        }

        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, treeId);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! windowId[%{public}d]", windowId);
            std::list<AccessibilityElementInfo> infos;
            FocusMoveResult result;
            callback->SetFocusMoveSearchWithConditionResult(infos, result, requestId);
            syncPromise->set_value(ret);
            return;
        }
        accountData->GetElementOperatorManager().AddRequestId(windowId, treeId, requestId, callback);
        elementOperator->FocusMoveSearchWithCondition(elementInfo, param, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "FocusMoveSearchWithCondition");
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait SearchElementInfosByText result, requestId: %{public}d", requestId);
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::UpdateCustomAccessibilityProperty(const int64_t elementId,
    const int32_t windowId, const AccessibilityVirtualNode& accessibilityVirtualNode, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    HILOG_DEBUG("elementId[%{public}" PRId64 "], windowId[%{public}d], requestId[%{public}d]",
        elementId, windowId, requestId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t tree = Utils::GetTreeIdBySplitElementId(elementId);
    eventHandler_->PostTask([accountId, clientName, syncPromise, windowId, elementId, tree,
        accessibilityVirtualNode, requestId, callback, this]() {
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, tree);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            if (callback != nullptr) {
                callback->SetUpdateCustomAccessibilityPropertyResult(
                    OperateVirtualNodeResult::ACCESSIBILITY_ELEMENT_NOT_EXIST, requestId);
            }
            syncPromise->set_value(ret);
            return;
        }

        auto& awm = Singleton<AccessibilityWindowManager>::GetInstance();
        int64_t realElementId = awm.GetSceneBoardElementId(windowId, elementId);
        elementOperator->UpdateCustomAccessibilityProperty(realElementId, accessibilityVirtualNode,
            requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "UpdateCustomAccessibilityProperty");

    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait UpdateCustomAccessibilityProperty result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::AddAccessibilityVirtualNode(const int64_t rootId,
    const int32_t windowId, const std::vector<AccessibilityVirtualNode> &nodes, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    HILOG_DEBUG("rootId[%{public}" PRId64 "], windowId[%{public}d], requestId[%{public}d]",
        rootId, windowId, requestId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t tree = Utils::GetTreeIdBySplitElementId(rootId);
    eventHandler_->PostTask([accountId, clientName, syncPromise, windowId, rootId, tree,
        nodes, requestId, callback, this]() {
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, tree);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            if (callback != nullptr) {
                callback->SetAddAccessibilityVirtualNodeResult(
                    OperateVirtualNodeResult::ACCESSIBILITY_ELEMENT_NOT_EXIST, requestId);
            }
            syncPromise->set_value(ret);
            return;
        }

        auto& awm = Singleton<AccessibilityWindowManager>::GetInstance();
        int64_t realRootId = awm.GetSceneBoardElementId(windowId, rootId);
        elementOperator->AddAccessibilityVirtualNode(realRootId, nodes, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "AddAccessibilityVirtualNode");
 
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait AddAccessibilityVirtualNode result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}

RetError AccessibleAbilityChannel::RemoveAccessibilityVirtualNode(const int64_t id,
    const int32_t windowId, const int32_t requestId,
    const sptr<IAccessibilityElementOperatorCallback> &callback)
{
    HILOG_DEBUG("id[%{public}" PRId64 "], windowId[%{public}d], requestId[%{public}d]",
        id, windowId, requestId);
    Singleton<AccessibleAbilityManagerService>::GetInstance().PostDelayUnloadTask();
    if (eventHandler_ == nullptr) {
        HILOG_ERROR("eventHandler_ is nullptr.");
        return RET_ERR_NULLPTR;
    }

    int32_t accountId = accountId_;
    std::string clientName = clientName_;
    std::shared_ptr<ffrt::promise<RetError>> syncPromise = std::make_shared<ffrt::promise<RetError>>();
    ffrt::future syncFuture = syncPromise->get_future();
    int32_t tree = Utils::GetTreeIdBySplitElementId(id);
    eventHandler_->PostTask([accountId, clientName, syncPromise, windowId, id, tree,
        requestId, callback, this]() {
        sptr<IAccessibilityElementOperator> elementOperator = nullptr;
        RetError ret = GetElementOperator(accountId, windowId, FOCUS_TYPE_INVALID,
            clientName, elementOperator, tree);
        if (ret != RET_OK) {
            HILOG_ERROR("Get elementOperator failed! accessibilityWindowId[%{public}d]", windowId);
            if (callback != nullptr) {
                callback->SetRemoveAccessibilityVirtualNodeResult(
                    OperateVirtualNodeResult::ACCESSIBILITY_ELEMENT_NOT_EXIST, requestId);
            }
            syncPromise->set_value(ret);
            return;
        }
 
        auto& awm = Singleton<AccessibilityWindowManager>::GetInstance();
        int64_t realId = awm.GetSceneBoardElementId(windowId, id);
        elementOperator->RemoveAccessibilityVirtualNode(realId, requestId, callback);
        syncPromise->set_value(RET_OK);
        }, "RemoveAccessibilityVirtualNode");
 
    ffrt::future_status wait = syncFuture.wait_for(std::chrono::milliseconds(TIME_OUT_OPERATOR));
    if (wait != ffrt::future_status::ready) {
        HILOG_ERROR("Failed to wait RemoveAccessibilityVirtualNode result");
        return RET_ERR_TIME_OUT;
    }
    return syncFuture.get();
}
} // namespace Accessibility
} // namespace OHOS