From 14ea52693831d00f074f1686c35aa7b4dba8885f Mon Sep 17 00:00:00 2001 From: qianyong325 Date: Mon, 28 Apr 2025 17:25:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=AD=97=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: qianyong325 --- common/include/global.h | 2 + common/include/variant_util.h | 11 + .../js_text_input_client_engine.cpp | 461 ++++++++++++------ .../js/napi/inputmethodclient/async_call.cpp | 61 ++- .../js/napi/inputmethodclient/async_call.h | 45 +- .../js_get_input_method_controller.cpp | 314 +++++------- ...s_get_input_method_textchange_listener.cpp | 12 +- .../js_get_input_method_textchange_listener.h | 4 + .../js/napi/inputmethodclient/js_utils.cpp | 2 + .../inputmethod_ability/IInputMethodAgent.idl | 2 + .../include/input_method_ability.h | 59 ++- .../include/input_method_agent_service_impl.h | 1 + .../src/input_method_ability.cpp | 278 +++++++---- .../src/input_method_agent_service_impl.cpp | 5 + .../IInputDataChannel.idl | 44 +- .../include/input_data_channel_proxy_wrap.h | 94 ++++ .../include/input_data_channel_service_impl.h | 44 +- .../include/input_method_utils.h | 24 + .../src/input_data_channel_proxy_wrap.cpp | 412 ++++++++++++++++ .../src/input_data_channel_service_impl.cpp | 141 ++++-- .../src/input_method_controller.cpp | 375 +++++++++++++- .../src/input_method_utils.cpp | 68 +++ frameworks/ndk/BUILD.gn | 2 + frameworks/ndk/src/native_capi_utils.cpp | 2 + .../inner_api/inputmethod_ability/BUILD.gn | 2 + .../include/input_method_controller.h | 29 ++ .../input_method_ability_exception_test.cpp | 2 +- .../src/input_method_ability_test.cpp | 2 + 28 files changed, 1883 insertions(+), 615 deletions(-) create mode 100644 frameworks/native/inputmethod_controller/include/input_data_channel_proxy_wrap.h create mode 100644 frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp diff --git a/common/include/global.h b/common/include/global.h index 3770c0141..f155c528b 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -109,6 +109,8 @@ enum { ERROR_OPERATE_PANEL, ERROR_IMA_CHANNEL_NULLPTR, ERROR_IMA_NULLPTR, + ERROR_RESPONSE_TIMEOUT, + ERROR_TOO_MANY_UNANSWERED_MESSAGE, ERROR_IMA_END, ERROR_IMC_BEGIN, diff --git a/common/include/variant_util.h b/common/include/variant_util.h index 0971bdc22..02f38d6af 100644 --- a/common/include/variant_util.h +++ b/common/include/variant_util.h @@ -18,6 +18,7 @@ #include #include +#include "global.h" #include "input_client_info.h" #include "input_method_utils.h" namespace OHOS { @@ -34,6 +35,16 @@ public: output = std::get(input); return true; } + + template + static bool GetValue(ResponseData &input, T &output) + { + if (!std::holds_alternative(input)) { + return false; + } + output = std::get(input); + return true; + } }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp index 3bd875f67..7072cb4b8 100644 --- a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp +++ b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp @@ -27,6 +27,7 @@ #include "wm_common.h" #include "res_config.h" #include "resource_manager.h" +#include "variant_util.h" namespace OHOS { namespace MiscServices { @@ -41,8 +42,6 @@ constexpr int32_t MAX_WAIT_TIME_MESSAGE_HANDLER = 2000; constexpr size_t ARGC_TWO = 2; constexpr size_t ARGC_ONE = 1; std::shared_ptr JsTextInputClientEngine::taskQueue_ = std::make_shared(); -BlockQueue JsTextInputClientEngine::privateCommandQueue_{ MAX_WAIT_TIME_PRIVATE_COMMAND }; -BlockQueue JsTextInputClientEngine::messageHandlerQueue_{ MAX_WAIT_TIME_MESSAGE_HANDLER }; std::mutex JsTextInputClientEngine::engineMutex_; std::shared_ptr JsTextInputClientEngine::textInputClientEngine_{ nullptr }; std::mutex JsTextInputClientEngine::eventHandlerMutex_; @@ -121,6 +120,7 @@ bool JsTextInputClientEngine::IsTargetDeviceType(int32_t resDeviceType) napi_value JsTextInputClientEngine::MoveCursor(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -132,19 +132,26 @@ napi_value JsTextInputClientEngine::MoveCursor(napi_env env, napi_callback_info napi_generic_failure); return status; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->MoveCursor(ctxt->num); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->MoveCursor(ctxt->num, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input)); // 2 means JsAPI:moveCursor has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::MoveCursorSync(napi_env env, napi_callback_info info) @@ -275,6 +282,7 @@ napi_status JsTextInputClientEngine::GetSelectMovement(napi_env env, napi_value napi_value JsTextInputClientEngine::SendKeyFunction(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -286,24 +294,32 @@ napi_value JsTextInputClientEngine::SendKeyFunction(napi_env env, napi_callback_ napi_status status = napi_get_boolean(env, ctxt->isSendKeyFunction, result); return status; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->SendFunctionKey(ctxt->action); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->isSendKeyFunction = true; - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + ctxt->isSendKeyFunction = true; + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SendFunctionKey(ctxt->action, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:sendKeyFunction has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SendPrivateCommand(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -313,25 +329,29 @@ napi_value JsTextInputClientEngine::SendPrivateCommand(napi_env env, napi_callba PARAM_CHECK_RETURN(env, TextConfig::IsPrivateCommandValid(ctxt->privateCommand), "commandData size limit 32KB, count limit 5.", TYPE_NONE, napi_generic_failure); ctxt->info = { std::chrono::system_clock::now(), ctxt->privateCommand }; - privateCommandQueue_.Push(ctxt->info); return status; }; auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - privateCommandQueue_.Wait(ctxt->info); - int32_t code = InputMethodAbility::GetInstance()->SendPrivateCommand(ctxt->privateCommand); - privateCommandQueue_.Pop(); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SendPrivateCommandEx(ctxt->privateCommand, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 1 means JsAPI:SendPrivateCommand has 1 param at most. - AsyncCall asyncCall(env, info, ctxt, 1); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::DeleteForwardSync(napi_env env, napi_callback_info info) @@ -358,6 +378,7 @@ napi_value JsTextInputClientEngine::DeleteForwardSync(napi_env env, napi_callbac napi_value JsTextInputClientEngine::DeleteForward(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto traceId = GenerateTraceId(); InputMethodSyncTrace tracer("JS_DeleteForward_Start", traceId); auto ctxt = std::make_shared(); @@ -374,21 +395,28 @@ napi_value JsTextInputClientEngine::DeleteForward(napi_env env, napi_callback_in napi_status status = napi_get_boolean(env, ctxt->isDeleteForward, result); return status; }; - auto exec = [ctxt, traceId](AsyncCall::Context *ctx) { + auto exec = [ctxt, traceId, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { InputMethodSyncTrace tracer("JS_DeleteForward_Exec", traceId); - int32_t code = InputMethodAbility::GetInstance()->DeleteForward(ctxt->length); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->isDeleteForward = true; - } else { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + ctxt->isDeleteForward = true; + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->DeleteForward(ctxt->length, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:deleteForward has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::DeleteBackwardSync(napi_env env, napi_callback_info info) @@ -414,6 +442,7 @@ napi_value JsTextInputClientEngine::DeleteBackwardSync(napi_env env, napi_callba napi_value JsTextInputClientEngine::DeleteBackward(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -426,24 +455,32 @@ napi_value JsTextInputClientEngine::DeleteBackward(napi_env env, napi_callback_i napi_status status = napi_get_boolean(env, ctxt->isDeleteBackward, result); return status; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->DeleteBackward(ctxt->length); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->isDeleteBackward = true; - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + ctxt->isDeleteBackward = true; + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->DeleteBackward(ctxt->length, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:deleteBackward has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::InsertText(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto traceId = GenerateTraceId(); InputMethodSyncTrace tracer("JS_InsertText_Start", traceId); auto ctxt = std::make_shared(); @@ -459,21 +496,29 @@ napi_value JsTextInputClientEngine::InsertText(napi_env env, napi_callback_info napi_status status = napi_get_boolean(env, ctxt->isInsertText, result); return status; }; - auto exec = [ctxt, traceId](AsyncCall::Context *ctx) { + auto exec = [ctxt, traceId, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { InputMethodSyncTrace tracer("JS_InsertText_Exec", traceId); - int32_t code = InputMethodAbility::GetInstance()->InsertText(ctxt->text); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->isInsertText = true; - } else { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + ctxt->isInsertText = true; + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + + int32_t code = InputMethodAbility::GetInstance()->InsertText(ctxt->text, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:insertText has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::InsertTextSync(napi_env env, napi_callback_info info) @@ -525,6 +570,7 @@ napi_value JsTextInputClientEngine::GetForwardSync(napi_env env, napi_callback_i napi_value JsTextInputClientEngine::GetForward(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto traceId = GenerateTraceId(); InputMethodSyncTrace tracer("JS_GetForward_Start", traceId); auto ctxt = std::make_shared(); @@ -541,22 +587,32 @@ napi_value JsTextInputClientEngine::GetForward(napi_env env, napi_callback_info *result = data; return napi_ok; }; - auto exec = [ctxt, traceId](AsyncCall::Context *ctx) { + auto exec = [ctxt, traceId, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { InputMethodSyncTrace tracer("JS_GetForward_Exec", traceId); + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR && VariantUtil::GetValue(data, ctxt->text)) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + return; + } + if (code == ErrorCode::NO_ERROR) { + code = ErrorCode::ERROR_BAD_PARAMETERS; + } + ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; std::u16string temp; - int32_t code = InputMethodAbility::GetInstance()->GetTextBeforeCursor(ctxt->length, temp); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->text = Str16ToStr8(temp); - } else { + int32_t code = InputMethodAbility::GetInstance()->GetTextBeforeCursor(ctxt->length, temp, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:getForward has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::GetBackwardSync(napi_env env, napi_callback_info info) @@ -587,6 +643,7 @@ napi_value JsTextInputClientEngine::GetBackwardSync(napi_env env, napi_callback_ napi_value JsTextInputClientEngine::GetBackward(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -600,21 +657,31 @@ napi_value JsTextInputClientEngine::GetBackward(napi_env env, napi_callback_info *result = data; return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR && VariantUtil::GetValue(data, ctxt->text)) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + return; + } + if (code == ErrorCode::NO_ERROR) { + code = ErrorCode::ERROR_BAD_PARAMETERS; + } + ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; std::u16string temp; - int32_t code = InputMethodAbility::GetInstance()->GetTextAfterCursor(ctxt->length, temp); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - ctxt->text = Str16ToStr8(temp); - } else { + int32_t code = InputMethodAbility::GetInstance()->GetTextAfterCursor(ctxt->length, temp, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:getBackward has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::GetEditorAttributeSync(napi_env env, napi_callback_info info) @@ -633,34 +700,46 @@ napi_value JsTextInputClientEngine::GetEditorAttributeSync(napi_env env, napi_ca napi_value JsTextInputClientEngine::GetEditorAttribute(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { *result = JsInputAttribute::Write(env, ctxt->inputAttribute); return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - TextTotalConfig config; - int32_t ret = InputMethodAbility::GetInstance()->GetTextConfig(config); - ctxt->inputAttribute = config.inputAttribute; - if (ret == ErrorCode::NO_ERROR) { - ctxt->SetState(napi_ok); - IMSA_HILOGD("inputPattern: %{public}d, enterKeyType: %{public}d, isTextPreviewSupported: %{public}d", - config.inputAttribute.inputPattern, config.inputAttribute.enterKeyType, - config.inputAttribute.isTextPreviewSupported); - } else { - IMSA_HILOGE("failed to get text config: %{public}d!", ret); + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + TextTotalConfig config = {}; + if (code == ErrorCode::NO_ERROR && VariantUtil::GetValue(data, config)) { + ctxt->inputAttribute = config.inputAttribute; + ctxt->SetState(napi_ok); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + return; + } + if (code == ErrorCode::NO_ERROR) { + code = ErrorCode::ERROR_BAD_PARAMETERS; + } + IMSA_HILOGE("failed to get text config: %{public}d!", code); ctxt->SetErrorCode(IMFErrorCode::EXCEPTION_IMCLIENT); ctxt->SetErrorMessage("failed to get text config!"); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + TextTotalConfig config; + int32_t ret = InputMethodAbility::GetInstance()->GetTextConfig(config, rspCallBack); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get text config: %{public}d!", ret); + ctxt->SetErrorCode(ret); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(nullptr, std::move(output)); // 1 means JsAPI:getEditorAttribute has 1 param at most. - AsyncCall asyncCall(env, info, ctxt, 1); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SelectByRange(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); IMSA_HILOGD("run in"); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { @@ -673,19 +752,26 @@ napi_value JsTextInputClientEngine::SelectByRange(napi_env env, napi_callback_in return status; }; auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->SelectByRange(ctxt->start, ctxt->end); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SelectByRange(ctxt->start, ctxt->end, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:selectByRange has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SelectByRangeSync(napi_env env, napi_callback_info info) @@ -737,6 +823,7 @@ napi_value JsTextInputClientEngine::SelectByMovementSync(napi_env env, napi_call napi_value JsTextInputClientEngine::SelectByMovement(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); IMSA_HILOGD("run in"); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { @@ -749,23 +836,31 @@ napi_value JsTextInputClientEngine::SelectByMovement(napi_env env, napi_callback return status; }; auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->SelectByMovement(ctxt->direction); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SelectByMovement(ctxt->direction, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:selectByMovement has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SendExtendAction(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -774,22 +869,30 @@ napi_value JsTextInputClientEngine::SendExtendAction(napi_env env, napi_callback TYPE_NONE, napi_generic_failure); return status; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->SendExtendAction(ctxt->action); - if (code == ErrorCode::NO_ERROR) { - ctxt->SetState(napi_ok); - return; + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->SetState(napi_ok); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SendExtendAction(ctxt->action, rspCallBack); + if (code != ErrorCode::NO_ERROR) { + ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } - ctxt->SetErrorCode(code); }; ctxt->SetAction(std::move(input)); // 2 means JsAPI:sendExtendAction has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::GetTextIndexAtCursor(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); IMSA_HILOGD("GetTextIndexAtCursor"); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { @@ -798,23 +901,35 @@ napi_value JsTextInputClientEngine::GetTextIndexAtCursor(napi_env env, napi_call auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_create_int32(env, ctxt->index, result); }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t code = InputMethodAbility::GetInstance()->GetTextIndexAtCursor(ctxt->index); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR && VariantUtil::GetValue(data, ctxt->index)) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + return; + } + if (code == ErrorCode::NO_ERROR) { + code = ErrorCode::ERROR_BAD_PARAMETERS; + } + ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->GetTextIndexAtCursor(ctxt->index, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 1 means JsAPI:getTextIndexAtCursor has 1 param at most. - AsyncCall asyncCall(env, info, ctxt, 1); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SetPreviewText(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto traceId = GenerateTraceId(); InputMethodSyncTrace tracer("JS_SetPreviewText_Start", traceId); IMSA_HILOGD("JsTextInputClientEngine in"); @@ -829,24 +944,31 @@ napi_value JsTextInputClientEngine::SetPreviewText(napi_env env, napi_callback_i InputMethodSyncTrace tracer("JS_SetPreviewText_Complete", traceId); return napi_ok; }; - auto exec = [ctxt, traceId](AsyncCall::Context *ctx) { + auto exec = [ctxt, traceId, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { InputMethodSyncTrace tracer("JS_SetPreviewText_Exec", traceId); - int32_t code = InputMethodAbility::GetInstance()->SetPreviewText(ctxt->text, ctxt->range); - if (code == ErrorCode::NO_ERROR) { - IMSA_HILOGD("exec setPreviewText success"); - ctxt->SetState(napi_ok); - } else if (code == ErrorCode::ERROR_INVALID_RANGE) { - ctxt->SetErrorCode(code); - ctxt->SetErrorMessage("range should be included in preview text range, otherwise should be included in " - "total text range!"); - } else { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + IMSA_HILOGD("exec setPreviewText success"); + ctxt->SetState(napi_ok); + } else if (code == ErrorCode::ERROR_INVALID_RANGE) { + ctxt->SetErrorCode(code); + ctxt->SetErrorMessage("range should be included in preview text range, otherwise should be included in " + "total text range!"); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SetPreviewText(ctxt->text, ctxt->range, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 2 means JsAPI:setPreviewText needs 2 params at most - AsyncCall asyncCall(env, info, ctxt, 2); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 2); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::SetPreviewTextSync(napi_env env, napi_callback_info info) @@ -875,6 +997,7 @@ napi_value JsTextInputClientEngine::SetPreviewTextSync(napi_env env, napi_callba napi_value JsTextInputClientEngine::FinishTextPreview(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto traceId = GenerateTraceId(); InputMethodSyncTrace tracer("JS_FinishTextPreview_Start", traceId); IMSA_HILOGD("start."); @@ -886,20 +1009,27 @@ napi_value JsTextInputClientEngine::FinishTextPreview(napi_env env, napi_callbac InputMethodSyncTrace tracer("JS_FinishTextPreview_Complete", traceId); return napi_ok; }; - auto exec = [ctxt, traceId](AsyncCall::Context *ctx) { + auto exec = [ctxt, traceId, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { InputMethodSyncTrace tracer("JS_FinishTextPreview_Exec", traceId); - int32_t code = InputMethodAbility::GetInstance()->FinishTextPreview(false); - if (code == ErrorCode::NO_ERROR) { - IMSA_HILOGI("exec finishTextPreview success."); - ctxt->SetState(napi_ok); - } else { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + IMSA_HILOGI("exec finishTextPreview success."); + ctxt->SetState(napi_ok); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->FinishTextPreview(false, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), std::move(output)); // 0 means JsAPI:finishTextPreview needs no param - AsyncCall asyncCall(env, info, ctxt, 0); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 0); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_value JsTextInputClientEngine::FinishTextPreviewSync(napi_env env, napi_callback_info info) @@ -926,25 +1056,33 @@ napi_value JsTextInputClientEngine::GetTextIndexAtCursorSync(napi_env env, napi_ napi_value JsTextInputClientEngine::GetCallingWindowInfo(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); IMSA_HILOGD("start."); auto ctxt = std::make_shared(); auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { *result = JsCallingWindowInfo::Write(env, ctxt->windowInfo); return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - int32_t ret = InputMethodAbility::GetInstance()->GetCallingWindowInfo(ctxt->windowInfo); - if (ret == ErrorCode::NO_ERROR) { - IMSA_HILOGI("exec GetCallingWindowInfo success."); - ctxt->SetState(napi_ok); - return; + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + IMSA_HILOGI("exec GetCallingWindowInfo success."); + ctxt->SetState(napi_ok); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t ret = InputMethodAbility::GetInstance()->GetCallingWindowInfo(ctxt->windowInfo, rspCallBack); + if (ret != ErrorCode::NO_ERROR) { + ctxt->SetErrorCode(ret); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } - ctxt->SetErrorCode(ret); }; ctxt->SetAction(nullptr, std::move(output)); // 0 means JsAPI:getCallingWindowInfo needs no parameter. - AsyncCall asyncCall(env, info, ctxt, 0); - return ASYNC_POST(env, exec); + EditAsyncCall asyncCall(env, info, ctxt, 0); + return asyncCall.Call(env, exec, __FUNCTION__); } napi_status JsTextInputClientEngine::GetPreviewTextParam(napi_env env, size_t argc, napi_value *argv, @@ -1118,6 +1256,7 @@ bool JsAttachOptions::Read(napi_env env, napi_value jsObject, AttachOptions &att napi_value JsTextInputClientEngine::SendMessage(napi_env env, napi_callback_info info) { + std::shared_ptr handler = AppExecFwk::EventHandler::Current(); auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 0, "at least one parameter is required!", TYPE_NONE, napi_generic_failure); @@ -1139,23 +1278,27 @@ napi_value JsTextInputClientEngine::SendMessage(napi_env env, napi_callback_info PARAM_CHECK_RETURN(env, ArrayBuffer::IsSizeValid(ctxt->arrayBuffer), "msgId limit 256B and msgParam limit 128KB.", TYPE_NONE, napi_generic_failure); ctxt->info = { std::chrono::system_clock::now(), ctxt->arrayBuffer }; - messageHandlerQueue_.Push(ctxt->info); return napi_ok; }; - auto exec = [ctxt](AsyncCall::Context *ctx) { - messageHandlerQueue_.Wait(ctxt->info); - int32_t code = InputMethodAbility::GetInstance()->SendMessage(ctxt->arrayBuffer); - messageHandlerQueue_.Pop(); - if (code == ErrorCode::NO_ERROR) { - ctxt->status = napi_ok; - ctxt->SetState(ctxt->status); - } else { + auto exec = [ctxt, handler](AsyncCall::Context *ctx, AsyncCall::Context::CallBackAction completeFunc) { + auto rspCallBack = [ctxt, completeFunc, handler](int32_t code, ResponseData &data) -> void { + if (code == ErrorCode::NO_ERROR) { + ctxt->status = napi_ok; + ctxt->SetState(ctxt->status); + } else { + ctxt->SetErrorCode(code); + } + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); + }; + int32_t code = InputMethodAbility::GetInstance()->SendMessage(ctxt->arrayBuffer, rspCallBack); + if (code != ErrorCode::NO_ERROR) { ctxt->SetErrorCode(code); + completeFunc != nullptr ? completeFunc(handler) : IMSA_HILOGE("completeFunc is nullptr"); } }; ctxt->SetAction(std::move(input), nullptr); // 2 means JsAPI:sendMessage has 2 params at most. - AsyncCall asyncCall(env, info, ctxt, 2); + EditAsyncCall asyncCall(env, info, ctxt, 2); return asyncCall.Call(env, exec, "imaSendMessage"); } diff --git a/frameworks/js/napi/inputmethodclient/async_call.cpp b/frameworks/js/napi/inputmethodclient/async_call.cpp index 80d1720d3..42a167a2e 100644 --- a/frameworks/js/napi/inputmethodclient/async_call.cpp +++ b/frameworks/js/napi/inputmethodclient/async_call.cpp @@ -78,14 +78,8 @@ napi_value AsyncCall::Call(napi_env env, Context::ExecAction exec, const std::st } else { napi_get_undefined(env, &promise); } - napi_async_work work = context_->work; - napi_value resource = nullptr; - std::string name = "IMF_" + resourceName; - napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); - napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work); - context_->work = work; + CallImpl(env, context_, resourceName); context_ = nullptr; - napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated); return promise; } @@ -239,5 +233,58 @@ AsyncCall::InnerTask::~InnerTask() name, startTime, endTime, endTime - startTime); } } + +napi_value AsyncCall::Call(napi_env env, Context::AsynExecAction exec, const std::string &resourceName) +{ + if ((context_ == nullptr) || (context_->ctx == nullptr)) { + IMSA_HILOGE("context_ or context_->ctx is nullptr!"); + return nullptr; + } + context_->ctx->asyncExec_ = std::move(exec); + napi_value promise = nullptr; + if (context_->callback == nullptr) { + napi_create_promise(env, &context_->defer, &promise); + } else { + napi_get_undefined(env, &promise); + } + CallImpl(env, context_, resourceName); + context_ = nullptr; + return promise; +} + +void AsyncCall::OnExecuteAsync(napi_env env, void *data, Context::CallBackAction cb) +{ + AsyncContext *context = reinterpret_cast(data); + if (context == nullptr || context->ctx == nullptr) { + IMSA_HILOGE("context or context->ctx is nullptr!"); + return; + } + + context->ctx->AsyncExec(cb); +} + +void AsyncCall::CallImpl(napi_env env, void *data, const std::string &resourceName) +{ + AsyncContext *context = reinterpret_cast(data); + napi_async_work work = context->work; + napi_value resource = nullptr; + std::string name = "IMF_" + resourceName; + napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context, &work); + context->work = work; + napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated); +} + +void EditAsyncCall::CallImpl(napi_env env, void *data, const std::string &resourceName) +{ + AsyncContext *context = reinterpret_cast(data); + auto cb = [env, context, resourceName](std::shared_ptr handler) -> void { + auto task = [env, context]() -> void { + AsyncCall::OnComplete(env, context->ctx->GetState(), context); + }; + bool ret = handler->PostTask(task, "IMA" + resourceName, 0, AppExecFwk::EventQueue::Priority::VIP); + }; + AsyncCall::OnExecuteAsync(env, data, cb); +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/js/napi/inputmethodclient/async_call.h b/frameworks/js/napi/inputmethodclient/async_call.h index f37a26da7..df8b42232 100644 --- a/frameworks/js/napi/inputmethodclient/async_call.h +++ b/frameworks/js/napi/inputmethodclient/async_call.h @@ -22,16 +22,19 @@ #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "event_handler.h" namespace OHOS { namespace MiscServices { -class AsyncCall final { +class AsyncCall { public: class Context { public: using InputAction = std::function; using OutputAction = std::function; using ExecAction = std::function; + using CallBackAction = std::function handler)>; + using AsynExecAction = std::function; Context(InputAction input, OutputAction output) : input_(std::move(input)), output_(std::move(output)){}; virtual ~Context(){}; void SetAction(InputAction input, OutputAction output = nullptr) @@ -55,6 +58,11 @@ public: status_ = status; } + napi_status GetState() + { + return status_; + } + void SetAction(OutputAction output) { SetAction(nullptr, std::move(output)); @@ -90,11 +98,21 @@ public: exec_ = nullptr; }; + virtual void AsyncExec(CallBackAction cb) + { + if (asyncExec_ == nullptr) { + return; + } + asyncExec_(this, cb); + asyncExec_ = nullptr; + }; + protected: friend class AsyncCall; InputAction input_ = nullptr; OutputAction output_ = nullptr; ExecAction exec_ = nullptr; + AsynExecAction asyncExec_ = nullptr; napi_status status_ = napi_generic_failure; int32_t errorCode_ = 0; std::string errMessage_; @@ -118,14 +136,15 @@ public: AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t maxParamCount); ~AsyncCall(); napi_value Call(napi_env env, Context::ExecAction exec = nullptr, const std::string &resourceName = "AsyncCall"); + napi_value Call(napi_env env, Context::AsynExecAction exec = nullptr, + const std::string &resourceName = "AsyncCallEx"); napi_value Post(napi_env env, Context::ExecAction exec, std::shared_ptr queue, const char *func); napi_value SyncCall(napi_env env, Context::ExecAction exec = nullptr); private: - enum Arg : int { ARG_ERROR, ARG_DATA, ARG_BUTT }; - static void OnExecute(napi_env env, void *data); - static void OnExecuteSeq(napi_env env, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); + virtual void CallImpl(napi_env env, void *data, const std::string &resourceName); + +protected: struct AsyncContext { std::shared_ptr ctx = nullptr; napi_ref callback = nullptr; @@ -134,11 +153,27 @@ private: napi_async_work work = nullptr; std::shared_ptr queue = nullptr; }; + static void OnExecuteAsync(napi_env env, void *data, Context::CallBackAction cb); + static void OnComplete(napi_env env, napi_status status, void *data); + +private: + enum Arg : int { ARG_ERROR, ARG_DATA, ARG_BUTT }; + static void OnExecute(napi_env env, void *data); + static void OnExecuteSeq(napi_env env, void *data); static void DeleteContext(napi_env env, AsyncContext *context); AsyncContext *context_ = nullptr; napi_env env_ = nullptr; }; + +class EditAsyncCall : public AsyncCall { +public: + EditAsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t maxParamCount) + :AsyncCall(env, info, context, maxParamCount){}; + virtual ~EditAsyncCall(){}; +private: + void CallImpl(napi_env env, void *data, const std::string &resourceName) override; +}; } // namespace MiscServices } // namespace OHOS #endif // ASYNC_CALL_H diff --git a/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp b/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp index b08b9be8e..4d05fa03d 100644 --- a/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp +++ b/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp @@ -578,6 +578,9 @@ napi_value JsGetInputMethodController::Attach(napi_env env, napi_callback_info i { IMSA_HILOGI("run in."); InputMethodSyncTrace tracer("JsGetInputMethodController_Attach"); + if (JsGetInputMethodTextChangedListener::GetInstance()->GetEventHandler() == nullptr) { + JsGetInputMethodTextChangedListener::GetInstance()->SetEventHandler(AppExecFwk::EventHandler::Current()); + } auto ctxt = std::make_shared(); auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { PARAM_CHECK_RETURN(env, argc > 1, "at least two parameters is required!", TYPE_NONE, napi_generic_failure); @@ -883,26 +886,18 @@ void JsGetInputMethodController::InsertText(const std::u16string &text) static_cast(IInputDataChannelIpcCode::COMMAND_INSERT_TEXT), ErrorCode::ERROR_JS_CB_NOT_REGISTER); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("start."); - auto task = [entry]() { - auto getInsertTextProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getInsertTextProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_string_utf8(env, entry->text.c_str(), NAPI_AUTO_LENGTH, &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getInsertTextProperty }); + auto getInsertTextProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getInsertTextProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_string_utf8(env, entry->text.c_str(), NAPI_AUTO_LENGTH, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getInsertTextProperty }); } void JsGetInputMethodController::DeleteRight(int32_t length) @@ -916,27 +911,18 @@ void JsGetInputMethodController::DeleteRight(int32_t length) ErrorCode::ERROR_JS_CB_NOT_REGISTER); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("length: %{public}d", length); - - auto task = [entry]() { - auto getDeleteForwardProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getDeleteForwardProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, entry->length, &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getDeleteForwardProperty }); + auto getDeleteForwardProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getDeleteForwardProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, entry->length, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getDeleteForwardProperty }); } void JsGetInputMethodController::DeleteLeft(int32_t length) @@ -950,26 +936,18 @@ void JsGetInputMethodController::DeleteLeft(int32_t length) ErrorCode::ERROR_JS_CB_NOT_REGISTER); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("length: %{public}d", length); - auto task = [entry]() { - auto getDeleteBackwardProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getDeleteBackwardProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, entry->length, &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getDeleteBackwardProperty }); + auto getDeleteBackwardProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getDeleteBackwardProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, entry->length, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getDeleteBackwardProperty }); } void JsGetInputMethodController::SendKeyboardStatus(const KeyboardStatus &status) @@ -980,26 +958,18 @@ void JsGetInputMethodController::SendKeyboardStatus(const KeyboardStatus &status IMSA_HILOGD("failed to get uv entry."); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("status: %{public}d", static_cast(status)); - auto task = [entry]() { - auto getSendKeyboardStatusProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getSendKeyboardStatusProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, entry->keyboardStatus, &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getSendKeyboardStatusProperty }); + auto getSendKeyboardStatusProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getSendKeyboardStatusProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, entry->keyboardStatus, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getSendKeyboardStatusProperty }); } napi_value JsGetInputMethodController::CreateSendFunctionKey(napi_env env, int32_t functionKey) @@ -1023,31 +993,23 @@ void JsGetInputMethodController::SendFunctionKey(const FunctionKey &functionKey) IMSA_HILOGD("failed to get uv entry."); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("functionKey: %{public}d", static_cast(functionKey.GetEnterKeyType())); - auto task = [entry]() { - auto getSendFunctionKeyProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getSendFunctionKeyProperty the number of argc is invalid."); - return false; - } - napi_value functionKey = CreateSendFunctionKey(env, entry->enterKeyType); - if (functionKey == nullptr) { - IMSA_HILOGE("set select movement failed"); - return false; - } - // 0 means the first param of callback. - args[0] = functionKey; - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getSendFunctionKeyProperty }); + auto getSendFunctionKeyProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getSendFunctionKeyProperty the number of argc is invalid."); + return false; + } + napi_value functionKey = CreateSendFunctionKey(env, entry->enterKeyType); + if (functionKey == nullptr) { + IMSA_HILOGE("set select movement failed"); + return false; + } + // 0 means the first param of callback. + args[0] = functionKey; + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getSendFunctionKeyProperty }); } void JsGetInputMethodController::MoveCursor(const Direction direction) @@ -1058,26 +1020,18 @@ void JsGetInputMethodController::MoveCursor(const Direction direction) IMSA_HILOGD("failed to get uv entry."); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("direction: %{public}d", static_cast(direction)); - auto task = [entry]() { - auto getMoveCursorProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getMoveCursorProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, static_cast(entry->direction), &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getMoveCursorProperty }); + auto getMoveCursorProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getMoveCursorProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, static_cast(entry->direction), &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getMoveCursorProperty }); } void JsGetInputMethodController::HandleExtendAction(int32_t action) @@ -1088,88 +1042,58 @@ void JsGetInputMethodController::HandleExtendAction(int32_t action) IMSA_HILOGD("failed to get uv entry."); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("action: %{public}d", action); - auto task = [entry]() { - auto getHandleExtendActionProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc == ARGC_ZERO) { - IMSA_HILOGE("getHandleExtendActionProperty the number of argc is invalid."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, entry->action, &args[0]); - return true; - }; - // 1 means the callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, getHandleExtendActionProperty }); + auto getHandleExtendActionProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == ARGC_ZERO) { + IMSA_HILOGE("getHandleExtendActionProperty the number of argc is invalid."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, entry->action, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 1 means the callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, getHandleExtendActionProperty }); } std::u16string JsGetInputMethodController::GetText(const std::string &type, int32_t number) { - auto textResultHandler = std::make_shared>(MAX_TIMEOUT, ""); - auto entry = GetEntry(type, [&number, textResultHandler](UvEntry &entry) { + auto entry = GetEntry(type, [&number](UvEntry &entry) { entry.number = number; - entry.textResultHandler = textResultHandler; }); if (entry == nullptr) { IMSA_HILOGE("failed to get uv entry."); return u""; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return u""; - } IMSA_HILOGI("type: %{public}s, number: %{public}d.", type.c_str(), number); - auto task = [entry]() { - auto fillArguments = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - if (argc < 1) { - IMSA_HILOGE("argc is err."); - return false; - } - // 0 means the first param of callback. - napi_create_int32(env, entry->number, &args[0]); - return true; - }; - std::string text; - // 1 means callback has one param. - JsCallbackHandler::Traverse(entry->vecCopy, { 1, fillArguments }, text); - entry->textResultHandler->SetValue(text); + auto fillArguments = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc < 1) { + IMSA_HILOGE("argc is err."); + return false; + } + // 0 means the first param of callback. + napi_create_int32(env, entry->number, &args[0]); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); - return Str8ToStr16(textResultHandler->GetValue()); + std::string text; + // 1 means callback has one param. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, fillArguments }, text); + return Str8ToStr16(text); } int32_t JsGetInputMethodController::GetTextIndexAtCursor() { std::string type = "getTextIndexAtCursor"; - auto indexResultHandler = std::make_shared>(MAX_TIMEOUT, -1); - auto entry = - GetEntry(type, [indexResultHandler](UvEntry &entry) { entry.indexResultHandler = indexResultHandler; }); + auto entry = GetEntry(type, nullptr); if (entry == nullptr) { IMSA_HILOGE("failed to get uv entry!"); return -1; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return -1; - } IMSA_HILOGI("run in"); - auto task = [entry]() { - int32_t index = -1; - // 0 means callback has no params. - JsCallbackHandler::Traverse(entry->vecCopy, { 0, nullptr }, index); - entry->indexResultHandler->SetValue(index); - }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); - return indexResultHandler->GetValue(); + int32_t index = -1; + // 0 means callback has no params. + JsCallbackHandler::Traverse(entry->vecCopy, { 0, nullptr }, index); + return index; } int32_t JsGetInputMethodController::SetPreviewText(const std::u16string &text, const Range &range) @@ -1185,29 +1109,21 @@ int32_t JsGetInputMethodController::SetPreviewText(const std::u16string &text, c IMSA_HILOGD("failed to get uv entry!"); return ErrorCode::ERROR_NULL_POINTER; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } IMSA_HILOGI("previewText start."); - auto task = [entry]() { - auto getPreviewTextProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { - // 2 means the callback has two params. - if (argc < 2) { - return false; - } - // 0 means the first param of callback. - args[0] = JsUtil::GetValue(env, entry->text); - // 1 means the second param of callback. - args[1] = CreateSelectRange(env, entry->start, entry->end); - return true; - }; - - // 2 means the callback has two param. - JsCallbackHandler::Traverse(entry->vecCopy, { 2, getPreviewTextProperty }); + auto getPreviewTextProperty = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + // 2 means the callback has two params. + if (argc < 2) { + return false; + } + // 0 means the first param of callback. + args[0] = JsUtil::GetValue(env, entry->text); + // 1 means the second param of callback. + args[1] = CreateSelectRange(env, entry->start, entry->end); + return true; }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + + // 2 means the callback has two param. + JsCallbackHandler::Traverse(entry->vecCopy, { 2, getPreviewTextProperty }); return ErrorCode::NO_ERROR; } @@ -1219,17 +1135,9 @@ void JsGetInputMethodController::FinishTextPreview() IMSA_HILOGE("failed to get uv entry!"); return; } - auto eventHandler = GetEventHandler(); - if (eventHandler == nullptr) { - IMSA_HILOGE("eventHandler is nullptr!"); - return; - } IMSA_HILOGI("run in"); - auto task = [entry]() { - // 0 means callback has no params. - JsCallbackHandler::Traverse(entry->vecCopy, { 0, nullptr }); - }; - eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); + // 0 means callback has no params. + JsCallbackHandler::Traverse(entry->vecCopy, { 0, nullptr }); } std::shared_ptr JsGetInputMethodController::GetEventHandler() diff --git a/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.cpp b/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.cpp index 1f7aaa6cd..ac689ec05 100644 --- a/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.cpp +++ b/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #include "js_get_input_method_textchange_listener.h" - +#include "event_handler.h" #include "js_get_input_method_controller.h" namespace OHOS { namespace MiscServices { @@ -100,5 +100,15 @@ void JsGetInputMethodTextChangedListener::FinishTextPreview() { return JsGetInputMethodController::GetInstance()->FinishTextPreview(); } + +std::shared_ptr JsGetInputMethodTextChangedListener::GetEventHandler() const +{ + return handler_; +} + +void JsGetInputMethodTextChangedListener::SetEventHandler(std::shared_ptr handler) +{ + handler_ = handler; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.h b/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.h index cfefb2e3b..8674b68ca 100644 --- a/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.h +++ b/frameworks/js/napi/inputmethodclient/js_get_input_method_textchange_listener.h @@ -51,10 +51,14 @@ public: bool IsFromTs() override; int32_t SetPreviewText(const std::u16string &text, const Range &range) override; void FinishTextPreview() override; + std::shared_ptr GetEventHandler() const override; + void SetEventHandler(std::shared_ptr handler); private: static std::mutex listenerMutex_; static sptr inputMethodListener_; + + std::shared_ptr handler_ = nullptr; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/js/napi/inputmethodclient/js_utils.cpp b/frameworks/js/napi/inputmethodclient/js_utils.cpp index d8446aa23..546e07160 100644 --- a/frameworks/js/napi/inputmethodclient/js_utils.cpp +++ b/frameworks/js/napi/inputmethodclient/js_utils.cpp @@ -88,6 +88,8 @@ const std::map JsUtils::ERROR_CODE_MAP = { { ErrorCode::ERROR_IMSA_FORCE_STOP_IME_TIMEOUT, EXCEPTION_IMMS }, { ErrorCode::ERROR_IMC_NULLPTR, EXCEPTION_IMMS }, { ErrorCode::ERROR_DEVICE_UNSUPPORTED, EXCEPTION_UNSUPPORTED }, + { ErrorCode::ERROR_RESPONSE_TIMEOUT, EXCEPTION_IMCLIENT }, + { ErrorCode::ERROR_TOO_MANY_UNANSWERED_MESSAGE, EXCEPTION_IMCLIENT }, }; const std::map JsUtils::ERROR_CODE_CONVERT_MESSAGE_MAP = { diff --git a/frameworks/native/inputmethod_ability/IInputMethodAgent.idl b/frameworks/native/inputmethod_ability/IInputMethodAgent.idl index 30b2d4d6a..7e60b9a01 100644 --- a/frameworks/native/inputmethod_ability/IInputMethodAgent.idl +++ b/frameworks/native/inputmethod_ability/IInputMethodAgent.idl @@ -17,6 +17,7 @@ sequenceable input_attribute..OHOS.MiscServices.InputAttributeInner; sequenceable input_method_utils..OHOS.MiscServices.Value; sequenceable input_method_utils..OHOS.MiscServices.KeyEventValue; sequenceable input_method_utils..OHOS.MiscServices.ArrayBuffer; +sequenceable input_method_utils..OHOS.MiscServices.ResponseDataInner; interface OHOS.MiscServices.IKeyEventConsumer; interface OHOS.MiscServices.IInputMethodAgent { [ipccode 0] void DispatchKeyEvent([in] KeyEventValue keyEvent, [in] IKeyEventConsumer consumer); @@ -26,4 +27,5 @@ interface OHOS.MiscServices.IInputMethodAgent { void OnAttributeChange([in] InputAttributeInner attributeInner); void SendPrivateCommand([in] Value value); void SendMessage([in] ArrayBuffer arraybuffer); + void ResponseDataChannel([in] unsigned long msgId, [in] int code, [in] ResponseDataInner msg); } diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index 11591f1e1..6af50661a 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -41,6 +41,7 @@ #include "private_command_interface.h" #include "system_cmd_channel_proxy.h" #include "inputmethod_message_handler.h" +#include "input_data_channel_proxy_wrap.h" namespace OHOS { namespace MiscServices { @@ -54,28 +55,28 @@ public: int32_t UnRegisteredProxyIme(UnRegisteredType type); int32_t RegisterProxyIme(uint64_t displayId = DEFAULT_DISPLAY_ID); int32_t UnregisterProxyIme(uint64_t displayId); - int32_t InsertText(const std::string text); + int32_t InsertText(const std::string text, AsyncIpcCallBack callback = nullptr); void SetImeListener(std::shared_ptr imeListener); std::shared_ptr GetImeListener(); void SetKdListener(std::shared_ptr kdListener); void SetTextInputClientListener(std::shared_ptr textInputClientListener); - int32_t DeleteForward(int32_t length); - int32_t DeleteBackward(int32_t length); + int32_t DeleteForward(int32_t length, AsyncIpcCallBack callback = nullptr); + int32_t DeleteBackward(int32_t length, AsyncIpcCallBack callback = nullptr); int32_t HideKeyboardSelf(); - int32_t SendExtendAction(int32_t action); - int32_t GetTextBeforeCursor(int32_t number, std::u16string &text); - int32_t GetTextAfterCursor(int32_t number, std::u16string &text); - int32_t SendFunctionKey(int32_t funcKey); - int32_t MoveCursor(int32_t keyCode); - int32_t SelectByRange(int32_t start, int32_t end); - int32_t SelectByMovement(int32_t direction); + int32_t SendExtendAction(int32_t action, AsyncIpcCallBack callback = nullptr); + int32_t GetTextBeforeCursor(int32_t number, std::u16string &text, AsyncIpcCallBack callback = nullptr); + int32_t GetTextAfterCursor(int32_t number, std::u16string &text, AsyncIpcCallBack callback = nullptr); + int32_t SendFunctionKey(int32_t funcKey, AsyncIpcCallBack callback = nullptr); + int32_t MoveCursor(int32_t keyCode, AsyncIpcCallBack callback = nullptr); + int32_t SelectByRange(int32_t start, int32_t end, AsyncIpcCallBack callback = nullptr); + int32_t SelectByMovement(int32_t direction, AsyncIpcCallBack callback = nullptr); int32_t DispatchKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer); void SetCallingWindow(uint32_t windowId); int32_t GetEnterKeyType(int32_t &keyType); int32_t GetInputPattern(int32_t &inputPattern); - int32_t GetTextIndexAtCursor(int32_t &index); - int32_t GetTextConfig(TextTotalConfig &textConfig); + int32_t GetTextIndexAtCursor(int32_t &index, AsyncIpcCallBack callback = nullptr); + int32_t GetTextConfig(TextTotalConfig &textConfig, AsyncIpcCallBack callback = nullptr, bool syncIpc = false); int32_t AdjustKeyboard(); int32_t CreatePanel(const std::shared_ptr &context, const PanelInfo &panelInfo, std::shared_ptr &inputMethodPanel); @@ -94,20 +95,24 @@ public: void OnClientInactive(const sptr &channel); void NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag); int32_t SendPrivateCommand(const std::unordered_map &privateCommand) override; + int32_t SendPrivateCommandEx(const std::unordered_map &privateCommand, + AsyncIpcCallBack callback = nullptr); int32_t ReceivePrivateCommand(const std::unordered_map &privateCommand) override; bool IsDefaultIme(); - int32_t GetCallingWindowInfo(CallingWindowInfo &windowInfo); - int32_t SetPreviewText(const std::string &text, const Range &range); - int32_t FinishTextPreview(bool isAsync); + int32_t GetCallingWindowInfo(CallingWindowInfo &windowInfo, AsyncIpcCallBack callback = nullptr); + int32_t SetPreviewText(const std::string &text, const Range &range, AsyncIpcCallBack callback = nullptr); + int32_t FinishTextPreview(bool isAsync, AsyncIpcCallBack callback = nullptr); int32_t NotifyPanelStatus(PanelType panelType, SysPanelStatus &sysPanelStatus); InputAttribute GetInputAttribute(); RequestKeyboardReason GetRequestKeyboardReason(); void OnSetInputType(InputType inputType); - int32_t SendMessage(const ArrayBuffer &arrayBuffer); + int32_t SendMessage(const ArrayBuffer &arrayBuffer, AsyncIpcCallBack callback = nullptr); int32_t RecvMessage(const ArrayBuffer &arrayBuffer); int32_t RegisterMsgHandler(const std::shared_ptr &msgHandler = nullptr); int32_t OnCallingDisplayIdChanged(uint64_t displayId); int32_t OnSendPrivateData(const std::unordered_map &privateCommand); + int32_t OnCallingDisplayChange(uint64_t displayId); + int32_t OnResponse(uint64_t msgId, int32_t code, const ResponseData &data); public: /* called from TaskManager worker thread */ @@ -130,7 +135,7 @@ private: std::mutex dataChannelLock_; sptr dataChannelObject_ = nullptr; - std::shared_ptr dataChannelProxy_ = nullptr; + std::shared_ptr dataChannelProxyWrap_ = nullptr; std::mutex systemCmdChannelLock_; sptr systemCmdChannelProxy_ = nullptr; @@ -151,7 +156,7 @@ private: void ClearSystemCmdChannel(); void SetInputDataChannel(const sptr &object); - std::shared_ptr GetInputDataChannelProxy(); + std::shared_ptr GetInputDataChannelProxyWrap(); void ClearDataChannel(const sptr &channel); void SetInputControlChannel(sptr &object); void ClearInputControlChannel(); @@ -176,18 +181,18 @@ private: int32_t HideKeyboardImplWithoutLock(int32_t cmdId, uint32_t sessionId); int32_t ShowKeyboardImplWithLock(int32_t cmdId); int32_t ShowKeyboardImplWithoutLock(int32_t cmdId); - void NotifyPanelStatusInfo(const PanelStatusInfo &info, std::shared_ptr &channelProxy); + void NotifyPanelStatusInfo(const PanelStatusInfo &info, std::shared_ptr &channelProxy); void ClearInputType(); std::shared_ptr GetMsgHandlerCallback(); int32_t StartInputInner(const InputClientInfo &clientInfo, bool isBindFromClient); - int32_t InsertTextInner(const std::string &text); - int32_t SetPreviewTextInner(const std::string &text, const Range &range); - int32_t DeleteForwardInner(int32_t length); - int32_t DeleteBackwardInner(int32_t length); - int32_t FinishTextPreviewInner(bool isAsync); - int32_t GetTextBeforeCursorInner(int32_t number, std::u16string &text); - int32_t GetTextAfterCursorInner(int32_t number, std::u16string &text); - int32_t GetTextIndexAtCursorInner(int32_t &index); + int32_t InsertTextInner(const std::string &text, AsyncIpcCallBack callback = nullptr); + int32_t SetPreviewTextInner(const std::string &text, const Range &range, AsyncIpcCallBack callback = nullptr); + int32_t DeleteForwardInner(int32_t length, AsyncIpcCallBack callback = nullptr); + int32_t DeleteBackwardInner(int32_t length, AsyncIpcCallBack callback = nullptr); + int32_t FinishTextPreviewInner(bool isAsync, AsyncIpcCallBack callback = nullptr); + int32_t GetTextBeforeCursorInner(int32_t number, std::u16string &text, AsyncIpcCallBack callback = nullptr); + int32_t GetTextAfterCursorInner(int32_t number, std::u16string &text, AsyncIpcCallBack callback = nullptr); + int32_t GetTextIndexAtCursorInner(int32_t &index, AsyncIpcCallBack callback = nullptr); void SetBindClientInfo(const InputClientInfo &clientInfo); HiSysEventClientInfo GetBindClientInfo(); void ReportImeStartInput(int32_t eventCode, int32_t errCode, bool isShowKeyboard, int64_t consumeTime = -1); diff --git a/frameworks/native/inputmethod_ability/include/input_method_agent_service_impl.h b/frameworks/native/inputmethod_ability/include/input_method_agent_service_impl.h index d0ad5498c..18c41b892 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_agent_service_impl.h +++ b/frameworks/native/inputmethod_ability/include/input_method_agent_service_impl.h @@ -38,6 +38,7 @@ public: ErrCode OnAttributeChange(const InputAttributeInner &attributeInner) override; ErrCode SendPrivateCommand(const Value &value) override; ErrCode SendMessage(const ArrayBuffer &arraybuffer) override; + ErrCode ResponseDataChannel(uint64_t msgId, int code, const ResponseDataInner &msg) override; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 5223766d1..dc241d1ca 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -37,6 +37,7 @@ #include "tasks/task.h" #include "tasks/task_imsa.h" #include "input_method_tools.h" +#include "variant_util.h" namespace OHOS { namespace MiscServices { @@ -335,7 +336,10 @@ void InputMethodAbility::ClearDataChannel(const sptr &channel) } if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) { dataChannelObject_ = nullptr; - dataChannelProxy_ = nullptr; + if (dataChannelProxyWrap_ != nullptr) { + dataChannelProxyWrap_->ClearMsg(true); + } + dataChannelProxyWrap_ = nullptr; IMSA_HILOGD("end."); } } @@ -509,7 +513,7 @@ int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId) } isShowAfterCreate_.store(true); IMSA_HILOGI("panel not create."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel != nullptr) { channel->SendKeyboardStatus(static_cast(KeyboardStatus::SHOW)); } @@ -520,14 +524,14 @@ int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId) void InputMethodAbility::NotifyPanelStatusInfo(const PanelStatusInfo &info) { // CANDIDATE_COLUMN not notify - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); NotifyPanelStatusInfo(info, channel); } int32_t InputMethodAbility::InvokeStartInputCallback(bool isNotifyInputStart) { TextTotalConfig textConfig = {}; - int32_t ret = GetTextConfig(textConfig); + int32_t ret = GetTextConfig(textConfig, nullptr, true); if (ret == ErrorCode::NO_ERROR) { textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName; return InvokeStartInputCallback(textConfig, isNotifyInputStart); @@ -609,44 +613,44 @@ bool InputMethodAbility::IsInputClientAttachOptionsChanged(RequestKeyboardReason return false; } -int32_t InputMethodAbility::InsertTextInner(const std::string &text) +int32_t InputMethodAbility::InsertTextInner(const std::string &text, AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_InsertText"); IMSA_HILOGD("InputMethodAbility start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } - return channel->InsertText(text); + return channel->InsertText(text, callback); } -int32_t InputMethodAbility::DeleteForwardInner(int32_t length) +int32_t InputMethodAbility::DeleteForwardInner(int32_t length, AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_DeleteForward"); IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } - return channel->DeleteForward(length); + return channel->DeleteForward(length, callback); } -int32_t InputMethodAbility::DeleteBackwardInner(int32_t length) +int32_t InputMethodAbility::DeleteBackwardInner(int32_t length, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } - return channel->DeleteBackward(length); + return channel->DeleteBackward(length, callback); } -int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey) +int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey, AsyncIpcCallBack callback) { - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; @@ -669,88 +673,88 @@ int32_t InputMethodAbility::HideKeyboardSelf() return ret == ErrorCode::ERROR_CLIENT_NULL_POINTER ? ret : ErrorCode::NO_ERROR; } -int32_t InputMethodAbility::SendExtendAction(int32_t action) +int32_t InputMethodAbility::SendExtendAction(int32_t action, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility, action: %{public}d.", action); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return channel->HandleExtendAction(action); + return channel->HandleExtendAction(action, callback); } -int32_t InputMethodAbility::GetTextBeforeCursorInner(int32_t number, std::u16string &text) +int32_t InputMethodAbility::GetTextBeforeCursorInner(int32_t number, std::u16string &text, AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_GetForward"); IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } std::string textu8 = ""; - auto ret = channel->GetTextBeforeCursor(number, textu8); + auto ret = channel->GetTextBeforeCursor(number, textu8, callback); text = Str8ToStr16(textu8); return ret; } -int32_t InputMethodAbility::GetTextAfterCursorInner(int32_t number, std::u16string &text) +int32_t InputMethodAbility::GetTextAfterCursorInner(int32_t number, std::u16string &text, AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_GetTextAfterCursor"); IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } std::string textu8 = ""; - auto ret = channel->GetTextAfterCursor(number, textu8); + auto ret = channel->GetTextAfterCursor(number, textu8, callback); text = Str8ToStr16(textu8); return ret; } -int32_t InputMethodAbility::MoveCursor(int32_t keyCode) +int32_t InputMethodAbility::MoveCursor(int32_t keyCode, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility, keyCode: %{public}d.", keyCode); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return channel->MoveCursor(keyCode); + return channel->MoveCursor(keyCode, callback); } -int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end) +int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility, start: %{public}d, end: %{public}d", start, end); if (start < 0 || end < 0) { IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d!", start, end); return ErrorCode::ERROR_PARAMETER_CHECK_FAILED; } - auto dataChannel = GetInputDataChannelProxy(); + auto dataChannel = GetInputDataChannelProxyWrap(); if (dataChannel == nullptr) { IMSA_HILOGE("datachannel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return dataChannel->SelectByRange(start, end); + return dataChannel->SelectByRange(start, end, callback); } -int32_t InputMethodAbility::SelectByMovement(int32_t direction) +int32_t InputMethodAbility::SelectByMovement(int32_t direction, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility, direction: %{public}d.", direction); - auto dataChannel = GetInputDataChannelProxy(); + auto dataChannel = GetInputDataChannelProxyWrap(); if (dataChannel == nullptr) { IMSA_HILOGE("datachannel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return dataChannel->SelectByMovement(direction, 0); + return dataChannel->SelectByMovement(direction, 0, callback); } int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType) { IMSA_HILOGD("InputMethodAbility start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; @@ -761,7 +765,7 @@ int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType) int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern) { IMSA_HILOGD("InputMethodAbility start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; @@ -769,32 +773,52 @@ int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern) return channel->GetInputPattern(inputPattern); } -int32_t InputMethodAbility::GetTextIndexAtCursorInner(int32_t &index) +int32_t InputMethodAbility::GetTextIndexAtCursorInner(int32_t &index, AsyncIpcCallBack callback) { IMSA_HILOGD("InputMethodAbility start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return channel->GetTextIndexAtCursor(index); + return channel->GetTextIndexAtCursor(index, callback); } -int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig) +int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig, AsyncIpcCallBack callback, bool syncIpc) { IMSA_HILOGI("InputMethodAbility start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - TextTotalConfigInner textConfigInner = InputMethodTools::GetInstance().TextTotalConfigToInner(textConfig); - auto ret = channel->GetTextConfig(textConfigInner); - if (ret == ErrorCode::NO_ERROR) { - textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(textConfigInner); + auto processAfterIpc = [this](TextTotalConfig &textConfig) -> void { textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName; textConfig.inputAttribute.callingDisplayId = GetInputAttribute().callingDisplayId; textConfig.inputAttribute.windowId = textConfig.windowId; + }; + AsyncIpcCallBack middle = nullptr; + if (callback != nullptr) { + middle = [callback, this, processAfterIpc](int32_t code, ResponseData &data) -> void { + TextTotalConfig textConfig = {}; + if (code == ErrorCode::NO_ERROR && VariantUtil::GetValue(data, textConfig)) { + processAfterIpc(textConfig); + ResponseData rsp = textConfig; + callback(code, rsp); + return; + } + if (code == ErrorCode::NO_ERROR) { + code = ErrorCode::ERROR_BAD_PARAMETERS; + } + callback(code, data); + }; + } + auto ret = channel->GetTextConfig(textConfig, middle, syncIpc); + if (middle != nullptr) { + return ret; + } + if (ret == ErrorCode::NO_ERROR) { + processAfterIpc(textConfig); } return ret; } @@ -808,14 +832,19 @@ void InputMethodAbility::SetInputDataChannel(const sptr &object) IMSA_HILOGE("failed to create channel proxy!"); return; } + auto channelWrap = std::make_shared(channelProxy); + if (channelWrap == nullptr) { + IMSA_HILOGE("failed to create channel wrap!"); + return; + } + dataChannelProxyWrap_ = channelWrap; dataChannelObject_ = object; - dataChannelProxy_ = channelProxy; } -std::shared_ptr InputMethodAbility::GetInputDataChannelProxy() +std::shared_ptr InputMethodAbility::GetInputDataChannelProxyWrap() { std::lock_guard lock(dataChannelLock_); - return dataChannelProxy_; + return dataChannelProxyWrap_; } void InputMethodAbility::SetInputControlChannel(sptr &object) @@ -1032,7 +1061,7 @@ int32_t InputMethodAbility::ShowPanel( if (inputMethodPanel == nullptr) { return ErrorCode::ERROR_IMA_NULLPTR; } - if (trigger == Trigger::IME_APP && GetInputDataChannelProxy() == nullptr) { + if (trigger == Trigger::IME_APP && GetInputDataChannelProxyWrap() == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } @@ -1087,7 +1116,7 @@ int32_t InputMethodAbility::NotifyPanelStatus(PanelType panelType, SysPanelStatu return ErrorCode::NO_ERROR; } // If it is not binding, do not need to notify the panel - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { return ErrorCode::NO_ERROR; } @@ -1165,7 +1194,7 @@ int32_t InputMethodAbility::HideKeyboard(Trigger trigger, uint32_t sessionId) } IMSA_HILOGI("panel is not created."); imeListener_->OnKeyboardStatus(false); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel != nullptr) { channel->SendKeyboardStatus(static_cast(KeyboardStatus::HIDE)); } @@ -1327,11 +1356,17 @@ void InputMethodAbility::OnClientInactive(const sptr &channel) IMSA_HILOGE("failed to create channel proxy!"); return; } + auto channelProxyWrap = std::make_shared(channelProxy); + if (channelProxyWrap == nullptr) { + IMSA_HILOGE("failed to create channel proxy warp!"); + return; + } auto panel = GetSoftKeyboardPanel(); if (imeListener_ != nullptr && panel != nullptr && panel->GetPanelFlag() != PanelFlag::FLG_FIXED) { imeListener_->OnKeyboardStatus(false); } - panels_.ForEach([this, &channelProxy](const PanelType &panelType, const std::shared_ptr &panel) { + panels_.ForEach([this, &channelProxyWrap]( + const PanelType &panelType, const std::shared_ptr &panel) { if (panelType != PanelType::SOFT_KEYBOARD || panel->GetPanelFlag() != PanelFlag::FLG_FIXED) { auto ret = panel->HidePanel(); if (ret != ErrorCode::NO_ERROR) { @@ -1343,7 +1378,7 @@ void InputMethodAbility::OnClientInactive(const sptr &channel) info.panelInfo.panelFlag = panel->GetPanelFlag(); info.visible = false; info.trigger = Trigger::IME_APP; - NotifyPanelStatusInfo(info, channelProxy); + NotifyPanelStatusInfo(info, channelProxyWrap); // finish previewing text when soft keyboard hides if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD) { FinishTextPreview(true); @@ -1357,7 +1392,7 @@ void InputMethodAbility::OnClientInactive(const sptr &channel) void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag) { - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return; @@ -1370,7 +1405,14 @@ void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag pa channel->NotifyKeyboardHeight(panelHeight); } -int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_map &privateCommand) +int32_t InputMethodAbility::SendPrivateCommand( + const std::unordered_map &privateCommand) +{ + return SendPrivateCommandEx(privateCommand, nullptr); +} + +int32_t InputMethodAbility::SendPrivateCommandEx( + const std::unordered_map &privateCommand, AsyncIpcCallBack callback) { if (!IsDefaultIme()) { IMSA_HILOGE("current is not default ime!"); @@ -1387,15 +1429,20 @@ int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_mapSendPrivateCommand(commandValueMap); + int ret = systemChannel->SendPrivateCommand(commandValueMap); + if (callback && ret == ErrorCode::NO_ERROR) { + ResponseData rspData = std::monostate{}; + callback(ret, rspData); + } + return ret; } else { - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } Value commandValueMap(privateCommand); - return channel->SendPrivateCommand(commandValueMap); + return channel->SendPrivateCommand(commandValueMap, callback); } } @@ -1410,39 +1457,34 @@ int32_t InputMethodAbility::ReceivePrivateCommand( return ErrorCode::NO_ERROR; } -int32_t InputMethodAbility::SetPreviewTextInner(const std::string &text, const Range &range) +int32_t InputMethodAbility::SetPreviewTextInner(const std::string &text, const Range &range, + AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_SetPreviewText"); - auto dataChannel = GetInputDataChannelProxy(); + auto dataChannel = GetInputDataChannelProxyWrap(); if (dataChannel == nullptr) { IMSA_HILOGE("dataChannel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } RangeInner rangeInner = InputMethodTools::GetInstance().RangeToInner(range); - return dataChannel->SetPreviewText(text, rangeInner); + return dataChannel->SetPreviewText(text, rangeInner, callback); } -int32_t InputMethodAbility::FinishTextPreviewInner(bool isAsync) +int32_t InputMethodAbility::FinishTextPreviewInner(bool isAsync, AsyncIpcCallBack callback) { InputMethodSyncTrace tracer("IMA_FinishTextPreview"); - auto dataChannel = GetInputDataChannelProxy(); + auto dataChannel = GetInputDataChannelProxyWrap(); if (dataChannel == nullptr) { IMSA_HILOGE("dataChannel is nullptr!"); return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR; } - int32_t ret; - if (isAsync == true) { - ret = dataChannel->FinishTextPreviewAsync(); - } else { - ret = dataChannel->FinishTextPreview(); - } - return ret; + return dataChannel->FinishTextPreview(isAsync, callback); } -int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo) +int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo, AsyncIpcCallBack callback) { IMSA_HILOGD("IMA start."); - auto channel = GetInputDataChannelProxy(); + auto channel = GetInputDataChannelProxyWrap(); if (channel == nullptr) { IMSA_HILOGE("channel is nullptr!"); return ErrorCode::ERROR_CLIENT_NOT_FOUND; @@ -1452,26 +1494,45 @@ int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo) IMSA_HILOGE("panel not found!"); return ErrorCode::ERROR_PANEL_NOT_FOUND; } - TextTotalConfig textConfig; - int32_t ret = GetTextConfig(textConfig); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("failed to get window id, ret: %{public}d!", ret); - return ErrorCode::ERROR_GET_TEXT_CONFIG; - } - ret = panel->SetCallingWindow(textConfig.windowId); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret); + auto processAfterIpc = [panel, &windowInfo](int32_t code, ResponseData data) -> int32_t { + if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get window id, ret: %{public}d!", code); + return ErrorCode::ERROR_GET_TEXT_CONFIG; + } + TextTotalConfig rspTextConfig = {}; + if (!VariantUtil::GetValue(data, rspTextConfig)) { + IMSA_HILOGE("failed to get TextConfig"); + return ErrorCode::ERROR_BAD_PARAMETERS; + } + int32_t ret = panel->SetCallingWindow(rspTextConfig.windowId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret); + return ret; + } + ret = panel->GetCallingWindowInfo(windowInfo); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret); + } return ret; + }; + AsyncIpcCallBack middle = nullptr; + if (callback != nullptr) { + middle = [callback, &windowInfo, panel, processAfterIpc](int32_t code, ResponseData &data) -> void { + int32_t ret = processAfterIpc(code, data); + ResponseData rspData = std::monostate{}; + callback(ret, rspData); + }; } - ret = panel->GetCallingWindowInfo(windowInfo); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret); + TextTotalConfig textConfig; + int32_t ret = GetTextConfig(textConfig, middle); + if (middle != nullptr) { + return ret; } - return ret; + return processAfterIpc(ret, textConfig); } void InputMethodAbility::NotifyPanelStatusInfo( - const PanelStatusInfo &info, std::shared_ptr &channelProxy) + const PanelStatusInfo &info, std::shared_ptr &channelProxy) { // CANDIDATE_COLUMN not notify if (info.panelInfo.panelFlag == PanelFlag::FLG_CANDIDATE_COLUMN) { @@ -1488,7 +1549,7 @@ void InputMethodAbility::NotifyPanelStatusInfo( } } -int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer) +int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer, AsyncIpcCallBack callback) { int32_t securityMode = INVALID_SECURITY_MODE; auto ret = GetSecurityMode(securityMode); @@ -1504,12 +1565,12 @@ int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer) IMSA_HILOGE("Security mode must be FULL!."); return ErrorCode::ERROR_SECURITY_MODE_OFF; } - auto dataChannel = GetInputDataChannelProxy(); + auto dataChannel = GetInputDataChannelProxyWrap(); if (dataChannel == nullptr) { IMSA_HILOGE("datachannel is nullptr."); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - return dataChannel->SendMessage(arrayBuffer); + return dataChannel->SendMessage(arrayBuffer, callback); } int32_t InputMethodAbility::RecvMessage(const ArrayBuffer &arrayBuffer) @@ -1565,74 +1626,74 @@ int32_t InputMethodAbility::StartInput(const InputClientInfo &clientInfo, bool i return ret; } -int32_t InputMethodAbility::InsertText(const std::string text) +int32_t InputMethodAbility::InsertText(const std::string text, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = InsertTextInner(text); + auto ret = InsertTextInner(text, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_INSERT_TEXT), ret, end - start); return ret; } -int32_t InputMethodAbility::DeleteForward(int32_t length) +int32_t InputMethodAbility::DeleteForward(int32_t length, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = DeleteForwardInner(length); + auto ret = DeleteForwardInner(length, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_DELETE_FORWARD), ret, end - start); return ret; } -int32_t InputMethodAbility::DeleteBackward(int32_t length) +int32_t InputMethodAbility::DeleteBackward(int32_t length, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = DeleteBackwardInner(length); + auto ret = DeleteBackwardInner(length, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_DELETE_BACKWARD), ret, end - start); return ret; } -int32_t InputMethodAbility::SetPreviewText(const std::string &text, const Range &range) +int32_t InputMethodAbility::SetPreviewText(const std::string &text, const Range &range, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = SetPreviewTextInner(text, range); + auto ret = SetPreviewTextInner(text, range, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_SET_PREVIEW_TEXT), ret, end - start); return ret; } -int32_t InputMethodAbility::FinishTextPreview(bool isSync) +int32_t InputMethodAbility::FinishTextPreview(bool isAsync, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = FinishTextPreviewInner(isSync); + auto ret = FinishTextPreviewInner(isAsync, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_FINISH_TEXT_PREVIEW), ret, end - start); return ret; } -int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text) +int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = GetTextBeforeCursorInner(number, text); + auto ret = GetTextBeforeCursorInner(number, text, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_GET_TEXT_BEFORE_CURSOR), ret, end - start); return ret; } -int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text) +int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = GetTextAfterCursorInner(number, text); + auto ret = GetTextAfterCursorInner(number, text, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_GET_TEXT_AFTER_CURSOR), ret, end - start); return ret; } -int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index) +int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index, AsyncIpcCallBack callback) { int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); - auto ret = GetTextIndexAtCursorInner(index); + auto ret = GetTextIndexAtCursorInner(index, callback); int64_t end = duration_cast(system_clock::now().time_since_epoch()).count(); ReportBaseTextOperation(static_cast(IInputDataChannelIpcCode::COMMAND_GET_TEXT_INDEX_AT_CURSOR), ret, end - start); @@ -1726,5 +1787,14 @@ int32_t InputMethodAbility::OnSendPrivateData(const std::unordered_mapOnResponse(msgId, code, data); + } + return 0; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp b/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp index 74b787493..36496f66f 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp @@ -85,5 +85,10 @@ ErrCode InputMethodAgentServiceImpl::SendMessage(const ArrayBuffer &arraybuffer) { return InputMethodAbility::GetInstance()->RecvMessage(arraybuffer); } + +ErrCode InputMethodAgentServiceImpl::ResponseDataChannel(uint64_t msgId, int code, const ResponseDataInner &msg) +{ + return InputMethodAbility::GetInstance()->OnResponse(msgId, code, msg.rspData); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/IInputDataChannel.idl b/frameworks/native/inputmethod_controller/IInputDataChannel.idl index b798d6359..c5681b777 100644 --- a/frameworks/native/inputmethod_controller/IInputDataChannel.idl +++ b/frameworks/native/inputmethod_controller/IInputDataChannel.idl @@ -21,26 +21,26 @@ sequenceable input_method_utils..OHOS.MiscServices.Value; sequenceable input_method_utils..OHOS.MiscServices.RangeInner; sequenceable input_method_utils..OHOS.MiscServices.ArrayBuffer; interface OHOS.MiscServices.IInputDataChannel { - [ipccode 0] void InsertText([in] String text); - void DeleteForward([in] int length); - void DeleteBackward([in] int length); - void GetTextBeforeCursor([in] int number, [out] String text); - void GetTextAfterCursor([in] int number, [out] String text); - void GetTextConfig([out] struct TextTotalConfigInner textConfiginner); - [oneway] void SendKeyboardStatus([in] int status); - void SendFunctionKey([in] int funcKey); - void MoveCursor([in] int keyCode); - void GetEnterKeyType([out] int keyType); - void GetInputPattern([out] int inputPattern); - void SelectByRange([in] int start, [in] int end); - void SelectByMovement([in] int direction, [in] int cursorMoveSkip); - void HandleExtendAction([in] int action); - void GetTextIndexAtCursor([out] int index); - [oneway] void NotifyPanelStatusInfo([in] PanelStatusInfoInner info); - [oneway] void NotifyKeyboardHeight([in] unsigned int height); - void SendPrivateCommand([in] Value value); - void SetPreviewText([in] String text, [in] RangeInner rangeInner); - [oneway] void FinishTextPreviewAsync(); - void FinishTextPreview(); - void SendMessage([in] ArrayBuffer arraybuffer); + [ipccode 0, oneway] void InsertText([in] String text, [in] unsigned long msgId); + [oneway] void DeleteForward([in] int length, [in] unsigned long msgId); + [oneway] void DeleteBackward([in] int length, [in] unsigned long msgId); + [oneway] void GetTextBeforeCursor([in] int number, [in] String text, [in] unsigned long msgId); + [oneway] void GetTextAfterCursor([in] int number, [in] String text, [in] unsigned long msgId); + [oneway] void GetTextConfig([in] struct TextTotalConfigInner textConfiginner, [in] unsigned long msgId); + void GetTextConfigSync([out] struct TextTotalConfigInner textConfiginner); + [oneway] void SendKeyboardStatus([in] int status, [in] unsigned long msgId); + [oneway] void SendFunctionKey([in] int funcKey, [in] unsigned long msgId); + [oneway] void MoveCursor([in] int keyCode, [in] unsigned long msgId); + [oneway] void GetEnterKeyType([in] int keyType, [in] unsigned long msgId); + [oneway] void GetInputPattern([in] int inputPattern, [in] unsigned long msgId); + [oneway] void SelectByRange([in] int start, [in] int end, [in] unsigned long msgId); + [oneway] void SelectByMovement([in] int direction, [in] int cursorMoveSkip, [in] unsigned long msgId); + [oneway] void HandleExtendAction([in] int action, [in] unsigned long msgId); + [oneway] void GetTextIndexAtCursor([in] int index, [in] unsigned long msgId); + [oneway] void NotifyPanelStatusInfo([in] PanelStatusInfoInner info, [in] unsigned long msgId); + [oneway] void NotifyKeyboardHeight([in] unsigned int height, [in] unsigned long msgId); + [oneway] void SendPrivateCommand([in] Value value, [in] unsigned long msgId); + [oneway] void SetPreviewText([in] String text, [in] RangeInner rangeInner, [in] unsigned long msgId); + [oneway] void FinishTextPreview([in] unsigned long msgId); + [oneway] void SendMessage([in] ArrayBuffer arraybuffer, [in] unsigned long msgId); } diff --git a/frameworks/native/inputmethod_controller/include/input_data_channel_proxy_wrap.h b/frameworks/native/inputmethod_controller/include/input_data_channel_proxy_wrap.h new file mode 100644 index 000000000..caa88a937 --- /dev/null +++ b/frameworks/native/inputmethod_controller/include/input_data_channel_proxy_wrap.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_DATA_CHANNEL_PROXY_WRAP_H +#define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_DATA_CHANNEL_PROXY_WRAP_H +#include +#include +#include +#include +#include +#include "input_data_channel_proxy.h" +#include "input_method_utils.h" + +namespace OHOS { +namespace MiscServices { +using AsyncIpcCallBack = std::function; +using ChannelWork = std::function channel)>; +using ChannelOutPut = std::function; +class InputDataChannelProxyWrap { +public: + + InputDataChannelProxyWrap(std::shared_ptr channel); + ~InputDataChannelProxyWrap(); + + int32_t InsertText(const std::string &text, AsyncIpcCallBack callback = nullptr); + int32_t DeleteForward(int32_t length, AsyncIpcCallBack callback = nullptr); + int32_t DeleteBackward(int32_t length, AsyncIpcCallBack callback = nullptr); + int32_t GetTextBeforeCursor(int32_t number, std::string &text, AsyncIpcCallBack callback = nullptr); + int32_t GetTextAfterCursor(int32_t number, std::string &text, AsyncIpcCallBack callback = nullptr); + void SendKeyboardStatus(int32_t status, bool isSync = false, AsyncIpcCallBack callback = nullptr); + int32_t SendFunctionKey(int32_t funcKey, AsyncIpcCallBack callback = nullptr); + int32_t MoveCursor(int32_t keyCode, AsyncIpcCallBack callback = nullptr); + int32_t GetEnterKeyType(int32_t &keyType, AsyncIpcCallBack callback = nullptr); + int32_t GetInputPattern(int32_t &inputPattern, AsyncIpcCallBack callback = nullptr); + int32_t SelectByRange(int32_t start, int32_t end, AsyncIpcCallBack callback = nullptr); + int32_t SelectByMovement(int32_t direction, int32_t cursorMoveSkip, AsyncIpcCallBack callback = nullptr); + int32_t HandleExtendAction(int32_t action, AsyncIpcCallBack callback = nullptr); + int32_t GetTextIndexAtCursor(int32_t &index, AsyncIpcCallBack callback = nullptr); + int32_t GetTextConfig(TextTotalConfig &textConfig, AsyncIpcCallBack callback = nullptr, bool ipcSync = false); + void NotifyPanelStatusInfo( + const PanelStatusInfoInner &info, bool isSync = false, AsyncIpcCallBack callback = nullptr); + void NotifyKeyboardHeight(uint32_t height, bool isSync = false, AsyncIpcCallBack callback = nullptr); + int32_t SendPrivateCommand(const Value &value, AsyncIpcCallBack callback = nullptr); + int32_t SetPreviewText(const std::string &text, const RangeInner &range, AsyncIpcCallBack callback = nullptr); + int32_t FinishTextPreview(bool isAsync, AsyncIpcCallBack callback = nullptr); + int32_t SendMessage(const ArrayBuffer &arraybuffer, AsyncIpcCallBack callback = nullptr); + +public: + int32_t ClearMsg(bool isNotify); + int32_t OnResponse(const uint64_t msgId, int32_t errorCode, const ResponseData &reply); + +private: + int32_t BeforeRequest(uint64_t &msgId, AsyncIpcCallBack callBack = nullptr, bool isSync = true); + int32_t WaitResponse(const uint64_t msgId, uint32_t timeout, int32_t &errorCode, ResponseData &data); + int32_t DelMsg(const uint64_t msgId); + uint64_t GetMsgId(); + int32_t HandleMsg(const uint64_t msgId, int32_t code, const ResponseData &data, int32_t defErrCode); + std::shared_ptr GetDataChannel(); + int32_t Request(AsyncIpcCallBack callback, ChannelWork work, bool isSync, ChannelOutPut output = nullptr); + +private: + struct AsyncMsgInfo { + bool isSync = false; + uint64_t msgId = 0; + AsyncIpcCallBack callBack = nullptr; + }; + + int32_t rspErrorCode_ = 0; + uint64_t msgId_ = 0; + uint64_t rspMsgId_ = 0; + std::mutex dataMutex_; + std::mutex rspMutex_; + std::mutex handerMutex_; + std::mutex channelMutex_; + ResponseData rspData_; + std::condition_variable rspCV_; + std::map msgList_; + std::shared_ptr channel_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_DATA_CHANNEL_PROXY_WRAP_H diff --git a/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h b/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h index 66ca83644..6c22d4953 100644 --- a/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h +++ b/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h @@ -33,28 +33,28 @@ public: InputDataChannelServiceImpl(); ~InputDataChannelServiceImpl(); - ErrCode InsertText(const std::string &text) override; - ErrCode DeleteForward(int32_t length) override; - ErrCode DeleteBackward(int32_t length) override; - ErrCode GetTextBeforeCursor(int32_t number, std::string &text) override; - ErrCode GetTextAfterCursor(int32_t number, std::string &text) override; - ErrCode GetTextConfig(TextTotalConfigInner &textConfigInner) override; - ErrCode SendKeyboardStatus(int32_t status) override; - ErrCode SendFunctionKey(int32_t funcKey) override; - ErrCode MoveCursor(int32_t keyCode) override; - ErrCode GetEnterKeyType(int32_t &keyType) override; - ErrCode GetInputPattern(int32_t &inputPattern) override; - ErrCode SelectByRange(int32_t start, int32_t end) override; - ErrCode SelectByMovement(int32_t direction, int32_t cursorMoveSkip) override; - ErrCode HandleExtendAction(int32_t action) override; - ErrCode GetTextIndexAtCursor(int32_t &index) override; - ErrCode NotifyPanelStatusInfo(const PanelStatusInfoInner &info) override; - ErrCode NotifyKeyboardHeight(uint32_t height) override; - ErrCode SendPrivateCommand(const Value &value) override; - ErrCode SetPreviewText(const std::string &text, const RangeInner &rangeInner) override; - ErrCode FinishTextPreview() override; - ErrCode FinishTextPreviewAsync() override; - ErrCode SendMessage(const ArrayBuffer &arraybuffer) override; + ErrCode InsertText(const std::string &text, uint64_t msgId) override; + ErrCode DeleteForward(int32_t length, uint64_t msgId) override; + ErrCode DeleteBackward(int32_t length, uint64_t msgId) override; + ErrCode GetTextBeforeCursor(int32_t number, const std::string &text, uint64_t msgId) override; + ErrCode GetTextAfterCursor(int32_t number, const std::string &text, uint64_t msgId) override; + ErrCode GetTextConfig(const TextTotalConfigInner &textConfigInner, uint64_t msgId) override; + ErrCode GetTextConfigSync(TextTotalConfigInner &textConfigInner) override; + ErrCode SendKeyboardStatus(int32_t status, uint64_t msgId) override; + ErrCode SendFunctionKey(int32_t funcKey, uint64_t msgId) override; + ErrCode MoveCursor(int32_t keyCode, uint64_t msgId) override; + ErrCode GetEnterKeyType(int32_t keyType, uint64_t msgId) override; + ErrCode GetInputPattern(int32_t inputPattern, uint64_t msgId) override; + ErrCode SelectByRange(int32_t start, int32_t end, uint64_t msgId) override; + ErrCode SelectByMovement(int32_t direction, int32_t cursorMoveSkip, uint64_t msgId) override; + ErrCode HandleExtendAction(int32_t action, uint64_t msgId) override; + ErrCode GetTextIndexAtCursor(int32_t index, uint64_t msgId) override; + ErrCode NotifyPanelStatusInfo(const PanelStatusInfoInner &info, uint64_t msgId) override; + ErrCode NotifyKeyboardHeight(uint32_t height, uint64_t msgId) override; + ErrCode SendPrivateCommand(const Value &value, uint64_t msgId) override; + ErrCode SetPreviewText(const std::string &text, const RangeInner &rangeInner, uint64_t msgId) override; + ErrCode FinishTextPreview(uint64_t msgId) override; + ErrCode SendMessage(const ArrayBuffer &arraybuffer, uint64_t msgId) override; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_method_utils.h b/frameworks/native/inputmethod_controller/include/input_method_utils.h index fd487218c..059805476 100644 --- a/frameworks/native/inputmethod_controller/include/input_method_utils.h +++ b/frameworks/native/inputmethod_controller/include/input_method_utils.h @@ -521,6 +521,30 @@ struct DetachOptions { bool isInactiveClient{ false }; bool isNotifyClientAsync{ false }; }; + +enum class ResponseDataType : uint64_t { + NALL_TYPE = 0, + STRING_TYPE, + INT32_TYPE, + CONFIG_TYPE +}; + +using ResponseData = std::variant; + +struct ResponseDataInner : public Parcelable { + bool ReadFromParcel(Parcel &in); + bool Marshalling(Parcel &out) const override; + static ResponseDataInner *Unmarshalling(Parcel &in) + { + ResponseDataInner *data = new (std::nothrow) ResponseDataInner(); + if (data && !data->ReadFromParcel(in)) { + delete data; + data = nullptr; + } + return data; + } + ResponseData rspData = std::monostate{}; +}; } // namespace MiscServices } // namespace OHOS #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H diff --git a/frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp b/frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp new file mode 100644 index 000000000..7924ff36c --- /dev/null +++ b/frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp @@ -0,0 +1,412 @@ +/* + * 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 "global.h" +#include +#include "string_ex.h" +#include "input_data_channel_proxy_wrap.h" +#include "input_method_tools.h" +#include "variant_util.h" +#include + +namespace OHOS { +namespace MiscServices { +constexpr std::size_t ASYNC_UNANSWERED_MAX_NUMBER = 50; +constexpr uint32_t ASYNC_REPLY_TIMEOUT = 100; // unit ms + +InputDataChannelProxyWrap::InputDataChannelProxyWrap(std::shared_ptr channel) +{ + auto now = std::chrono::steady_clock::now(); + auto duration = now.time_since_epoch(); + msgId_ = (uint64_t)std::chrono::duration_cast(duration).count(); + msgId_ = msgId_ ? msgId_ : ++msgId_; + + channel_ = channel; +} +InputDataChannelProxyWrap::~InputDataChannelProxyWrap() +{ + std::lock_guard lock(channelMutex_); + if (channel_ != nullptr) { + channel_ = nullptr; + } +} + +int32_t InputDataChannelProxyWrap::InsertText(const std::string &text, AsyncIpcCallBack callback) +{ + auto work = [text](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->InsertText(text, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::DeleteForward(int32_t length, AsyncIpcCallBack callback) +{ + auto work = [length](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->DeleteForward(length, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::DeleteBackward(int32_t length, AsyncIpcCallBack callback) +{ + auto work = [length](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->DeleteBackward(length, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::GetTextBeforeCursor(int32_t number, std::string &text, AsyncIpcCallBack callback) +{ + auto work = [number, text](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetTextBeforeCursor(number, text, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&text](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, text) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} + +int32_t InputDataChannelProxyWrap::GetTextAfterCursor(int32_t number, std::string &text, AsyncIpcCallBack callback) +{ + auto work = [number, text](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetTextAfterCursor(number, text, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&text](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, text) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} +void InputDataChannelProxyWrap::SendKeyboardStatus(int32_t status, bool isSync, AsyncIpcCallBack callback) +{ + auto work = [status](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SendKeyboardStatus(status, msgId); + }; + Request(callback, work, isSync); +} + +int32_t InputDataChannelProxyWrap::SendFunctionKey(int32_t funcKey, AsyncIpcCallBack callback) +{ + auto work = [funcKey](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SendFunctionKey(funcKey, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::MoveCursor(int32_t keyCode, AsyncIpcCallBack callback) +{ + auto work = [keyCode](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->MoveCursor(keyCode, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::GetEnterKeyType(int32_t &keyType, AsyncIpcCallBack callback) +{ + auto work = [keyType](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetEnterKeyType(keyType, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&keyType](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, keyType) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} + +int32_t InputDataChannelProxyWrap::GetInputPattern(int32_t &inputPattern, AsyncIpcCallBack callback) +{ + auto work = [inputPattern](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetInputPattern(inputPattern, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&inputPattern](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, inputPattern) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} + +int32_t InputDataChannelProxyWrap::SelectByRange(int32_t start, int32_t end, AsyncIpcCallBack callback) +{ + auto work = [start, end](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SelectByRange(start, end, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::SelectByMovement(int32_t direction, int32_t cursorMoveSkip, + AsyncIpcCallBack callback) +{ + auto work = [direction, cursorMoveSkip]( + uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SelectByMovement(direction, cursorMoveSkip, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::HandleExtendAction(int32_t action, AsyncIpcCallBack callback) +{ + auto work = [action](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->HandleExtendAction(action, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::GetTextIndexAtCursor(int32_t &index, AsyncIpcCallBack callback) +{ + auto work = [index](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetTextIndexAtCursor(index, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&index](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, index) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} + +int32_t InputDataChannelProxyWrap::GetTextConfig(TextTotalConfig &textConfig, AsyncIpcCallBack callback, bool ipcSync) +{ + auto channel = GetDataChannel(); + if (channel == nullptr) { + IMSA_HILOGE("data channel is nullptr!"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + int32_t ret = 0; + TextTotalConfigInner inner = InputMethodTools::GetInstance().TextTotalConfigToInner(textConfig); + if (ipcSync) { + ret = channel->GetTextConfigSync(inner); + if (ret == ErrorCode::NO_ERROR) { + textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(inner); + } + return ret; + } + + auto work = [inner](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->GetTextConfig(inner, msgId); + }; + ChannelOutPut output = nullptr; + if (!callback) { + output = [&textConfig](ResponseData &data) -> int32_t { + return VariantUtil::GetValue(data, textConfig) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_BAD_PARAMETERS; + }; + } + + return Request(callback, work, !callback, output); +} + +void InputDataChannelProxyWrap::NotifyPanelStatusInfo(const PanelStatusInfoInner &info, bool isSync, + AsyncIpcCallBack callback) +{ + auto work = [info](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->NotifyPanelStatusInfo(info, msgId); + }; + Request(callback, work, isSync); +} + +void InputDataChannelProxyWrap::NotifyKeyboardHeight(uint32_t height, bool isSync, AsyncIpcCallBack callback) +{ + auto work = [height](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->NotifyKeyboardHeight(height, msgId); + }; + Request(callback, work, isSync); +} + +int32_t InputDataChannelProxyWrap::SendPrivateCommand(const Value &value, AsyncIpcCallBack callback) +{ + auto work = [value](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SendPrivateCommand(value, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::SetPreviewText( + const std::string &text, const RangeInner &range, AsyncIpcCallBack callback) +{ + auto work = [text, range](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SetPreviewText(text, range, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::FinishTextPreview(bool isAsync, AsyncIpcCallBack callback) +{ + auto work = [](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->FinishTextPreview(msgId); + }; + return Request(callback, work, !isAsync); +} + +int32_t InputDataChannelProxyWrap::SendMessage(const ArrayBuffer &arraybuffer, AsyncIpcCallBack callback) +{ + auto work = [arraybuffer](uint64_t msgId, std::shared_ptr channel) -> int32_t { + return channel->SendMessage(arraybuffer, msgId); + }; + return Request(callback, work, !callback); +} + +int32_t InputDataChannelProxyWrap::Request( + AsyncIpcCallBack callback, ChannelWork work, bool isSync, ChannelOutPut output) +{ + auto channel = GetDataChannel(); + if (channel == nullptr) { + IMSA_HILOGE("data channel is nullptr!"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + uint64_t msgId = 0; + int32_t ret = BeforeRequest(msgId, callback, isSync); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("BeforeRequest error: %{public}d.", ret); + return ret; + } + ret = work(msgId, channel); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("work error: %{public}d.", ret); + DelMsg(msgId); + return ret; + } + if (isSync) { + int32_t errCode = 0; + ResponseData rspData = std::monostate{}; + ret = WaitResponse(msgId, ASYNC_REPLY_TIMEOUT, errCode, rspData); + if (ret == ErrorCode::NO_ERROR) { + ret = errCode; + if (output != nullptr) { + ret = output(rspData); + } + } + } + return ret; +} + +std::shared_ptr InputDataChannelProxyWrap::GetDataChannel() +{ + std::lock_guard lock(channelMutex_); + return channel_; +} + +uint64_t InputDataChannelProxyWrap::GetMsgId() +{ + return ++msgId_ ? msgId_ : ++msgId_; +} + +int32_t InputDataChannelProxyWrap::BeforeRequest(uint64_t &msgId, AsyncIpcCallBack callBack, bool isSync) +{ + std::lock_guard lock(dataMutex_); + if (msgList_.size() >= ASYNC_UNANSWERED_MAX_NUMBER) { + IMSA_HILOGW("async data channel, too many unanswered msg!"); + return ErrorCode::ERROR_TOO_MANY_UNANSWERED_MESSAGE; + } + AsyncMsgInfo msgInfo = { isSync, GetMsgId(), callBack }; + msgList_.insert({ msgInfo.msgId, msgInfo }); + msgId = msgInfo.msgId; + return ErrorCode::NO_ERROR; +} + +int32_t InputDataChannelProxyWrap::HandleMsg( + const uint64_t msgId, int32_t code, const ResponseData &data, int32_t defErrCode) +{ + for (auto it = msgList_.begin(); it != msgList_.end();) { + if (it->first > msgId) { + break; + } + int32_t currentCode = defErrCode; + ResponseData currentData = std::monostate{}; + if (it->first == msgId) { + currentCode = code; + currentData = data; + } + if (it->second.isSync) { + std::unique_lock lock(rspMutex_); + rspMsgId_ = it->first; + rspData_ = currentData; + rspErrorCode_ = currentCode; + rspCV_.notify_all(); + } else { + if (it->second.callBack) { + it->second.callBack(currentCode, currentData); + } + } + it = msgList_.erase(it); + } + return ErrorCode::NO_ERROR; +} + +int32_t InputDataChannelProxyWrap::ClearMsg(bool isNotify) +{ + IMSA_HILOGI("start ClearMsg"); + std::lock_guard lock(dataMutex_); + if (msgList_.empty()) { + return ErrorCode::NO_ERROR; + } + if (isNotify) { + int32_t errCode = ErrorCode::ERROR_CLIENT_NULL_POINTER; + ResponseData data = std::monostate{}; + return HandleMsg(msgList_.rbegin()->first, errCode, data, errCode); + } + msgList_.clear(); + return ErrorCode::NO_ERROR; +} + +int32_t InputDataChannelProxyWrap::OnResponse(const uint64_t msgId, int32_t errorCode, const ResponseData &reply) +{ + std::lock_guard lock(dataMutex_); + return HandleMsg(msgId, errorCode, reply, ErrorCode::ERROR_RESPONSE_TIMEOUT); +} + +int32_t InputDataChannelProxyWrap::WaitResponse(const uint64_t msgId, uint32_t timeout, int32_t &errorCode, + ResponseData &data) +{ + std::unique_lock lock(rspMutex_); + auto ret = rspCV_.wait_for(lock, std::chrono::milliseconds(timeout), + [this, msgId] { return this->rspMsgId_ == msgId; }); + if (ret) { + errorCode = rspErrorCode_; + data = rspData_; + return ErrorCode::NO_ERROR; + } + return ErrorCode::ERROR_RESPONSE_TIMEOUT; +} + +int32_t InputDataChannelProxyWrap::DelMsg(const uint64_t msgId) +{ + std::lock_guard lock(dataMutex_); + auto it = msgList_.find(msgId); + if (it != msgList_.end()) { + msgList_.erase(it); + } + return ErrorCode::NO_ERROR; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp b/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp index 4890247b9..598e07260 100644 --- a/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp +++ b/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp @@ -23,141 +23,196 @@ #include "itypes_util.h" #include "message.h" #include "input_method_tools.h" +#include namespace OHOS { namespace MiscServices { InputDataChannelServiceImpl::InputDataChannelServiceImpl() {} InputDataChannelServiceImpl::~InputDataChannelServiceImpl() {} -ErrCode InputDataChannelServiceImpl::InsertText(const std::string &text) +ErrCode InputDataChannelServiceImpl::InsertText(const std::string &text, uint64_t msgId) { - return InputMethodController::GetInstance()->InsertText(Str8ToStr16(text)); + int32_t ret = InputMethodController::GetInstance()->InsertText(Str8ToStr16(text)); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::DeleteForward(int32_t length) +ErrCode InputDataChannelServiceImpl::DeleteForward(int32_t length, uint64_t msgId) { - return InputMethodController::GetInstance()->DeleteForward(length); + int32_t ret = InputMethodController::GetInstance()->DeleteForward(length); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::DeleteBackward(int32_t length) +ErrCode InputDataChannelServiceImpl::DeleteBackward(int32_t length, uint64_t msgId) { - return InputMethodController::GetInstance()->DeleteBackward(length); + int32_t ret = InputMethodController::GetInstance()->DeleteBackward(length); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::GetTextBeforeCursor(int32_t number, std::string &text) +ErrCode InputDataChannelServiceImpl::GetTextBeforeCursor(int32_t number, const std::string &text, uint64_t msgId) { std::u16string textu16 = Str8ToStr16(text); auto ret = InputMethodController::GetInstance()->GetLeft(number, textu16); - text = Str16ToStr8(textu16); + ResponseData data = Str16ToStr8(textu16); + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); return ret; } -ErrCode InputDataChannelServiceImpl::GetTextAfterCursor(int32_t number, std::string &text) +ErrCode InputDataChannelServiceImpl::GetTextAfterCursor(int32_t number, const std::string &text, uint64_t msgId) { std::u16string textu16 = Str8ToStr16(text); - auto ret = InputMethodController::GetInstance()->GetRight(number, textu16); - text = Str16ToStr8(textu16); + ResponseData data = Str16ToStr8(textu16); + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); return ret; } -ErrCode InputDataChannelServiceImpl::GetTextIndexAtCursor(int32_t &index) +ErrCode InputDataChannelServiceImpl::GetTextIndexAtCursor(int32_t index, uint64_t msgId) { - return InputMethodController::GetInstance()->GetTextIndexAtCursor(index); + auto ret = InputMethodController::GetInstance()->GetTextIndexAtCursor(index); + ResponseData data = index; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::GetEnterKeyType(int32_t &keyType) +ErrCode InputDataChannelServiceImpl::GetEnterKeyType(int32_t keyType, uint64_t msgId) { - return InputMethodController::GetInstance()->GetEnterKeyType(keyType); + auto ret = InputMethodController::GetInstance()->GetEnterKeyType(keyType); + ResponseData data = keyType; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::GetInputPattern(int32_t &inputPattern) +ErrCode InputDataChannelServiceImpl::GetInputPattern(int32_t inputPattern, uint64_t msgId) { - return InputMethodController::GetInstance()->GetInputPattern(inputPattern); + auto ret = InputMethodController::GetInstance()->GetInputPattern(inputPattern); + ResponseData data = inputPattern; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::GetTextConfig(TextTotalConfigInner &textConfigInner) +ErrCode InputDataChannelServiceImpl::GetTextConfig(const TextTotalConfigInner &textConfigInner, uint64_t msgId) +{ + TextTotalConfig textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(textConfigInner); + auto ret = InputMethodController::GetInstance()->GetTextConfig(textConfig); + ResponseData data = textConfig; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; +} + +ErrCode InputDataChannelServiceImpl::GetTextConfigSync(TextTotalConfigInner &textConfigInner) { TextTotalConfig textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(textConfigInner); - auto ret = InputMethodController::GetInstance()->GetTextConfig(textConfig); textConfigInner = InputMethodTools::GetInstance().TextTotalConfigToInner(textConfig); return ret; } -ErrCode InputDataChannelServiceImpl::SendKeyboardStatus(int32_t status) +ErrCode InputDataChannelServiceImpl::SendKeyboardStatus(int32_t status, uint64_t msgId) { InputMethodController::GetInstance()->SendKeyboardStatus(static_cast(status)); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ERR_OK, data); return ERR_OK; } -ErrCode InputDataChannelServiceImpl::SendFunctionKey(int32_t funcKey) +ErrCode InputDataChannelServiceImpl::SendFunctionKey(int32_t funcKey, uint64_t msgId) { - return InputMethodController::GetInstance()->SendFunctionKey(funcKey); + auto ret = InputMethodController::GetInstance()->SendFunctionKey(funcKey); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::MoveCursor(int32_t keyCode) +ErrCode InputDataChannelServiceImpl::MoveCursor(int32_t keyCode, uint64_t msgId) { - return InputMethodController::GetInstance()->MoveCursor(static_cast(keyCode)); + auto ret = InputMethodController::GetInstance()->MoveCursor(static_cast(keyCode)); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::SelectByRange(int32_t start, int32_t end) +ErrCode InputDataChannelServiceImpl::SelectByRange(int32_t start, int32_t end, uint64_t msgId) { InputMethodController::GetInstance()->SelectByRange(start, end); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ERR_OK, data); return ERR_OK; } -ErrCode InputDataChannelServiceImpl::SelectByMovement(int32_t direction, int32_t cursorMoveSkip) +ErrCode InputDataChannelServiceImpl::SelectByMovement(int32_t direction, int32_t cursorMoveSkip, uint64_t msgId) { InputMethodController::GetInstance()->SelectByMovement(direction, cursorMoveSkip); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ERR_OK, data); return ERR_OK; } -ErrCode InputDataChannelServiceImpl::HandleExtendAction(int32_t action) +ErrCode InputDataChannelServiceImpl::HandleExtendAction(int32_t action, uint64_t msgId) { - return InputMethodController::GetInstance()->HandleExtendAction(action); + auto ret = InputMethodController::GetInstance()->HandleExtendAction(action); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::NotifyPanelStatusInfo(const PanelStatusInfoInner &info) +ErrCode InputDataChannelServiceImpl::NotifyPanelStatusInfo(const PanelStatusInfoInner &info, uint64_t msgId) { PanelStatusInfo panelStatusInfo = InputMethodTools::GetInstance().InnerToPanelStatusInfo(info); InputMethodController::GetInstance()->NotifyPanelStatusInfo(panelStatusInfo); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ERR_OK, data); return ERR_OK; } -ErrCode InputDataChannelServiceImpl::NotifyKeyboardHeight(uint32_t height) +ErrCode InputDataChannelServiceImpl::NotifyKeyboardHeight(uint32_t height, uint64_t msgId) { InputMethodController::GetInstance()->NotifyKeyboardHeight(height); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ERR_OK, data); return ERR_OK; } ErrCode InputDataChannelServiceImpl::SendPrivateCommand( - const Value &value) + const Value &value, uint64_t msgId) { std::unordered_map privateCommand; privateCommand = value.valueMap; - return InputMethodController::GetInstance()->ReceivePrivateCommand(privateCommand); + auto ret = InputMethodController::GetInstance()->ReceivePrivateCommand(privateCommand); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::SetPreviewText(const std::string &text, const RangeInner &rangeInner) +ErrCode InputDataChannelServiceImpl::SetPreviewText( + const std::string &text, const RangeInner &rangeInner, uint64_t msgId) { Range range = InputMethodTools::GetInstance().InnerToRange(rangeInner); - return InputMethodController::GetInstance()->SetPreviewText(text, range); -} - -ErrCode InputDataChannelServiceImpl::FinishTextPreview() -{ - return InputMethodController::GetInstance()->FinishTextPreview(); + auto ret = InputMethodController::GetInstance()->SetPreviewText(text, range); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::FinishTextPreviewAsync() +ErrCode InputDataChannelServiceImpl::FinishTextPreview(uint64_t msgId) { - return InputMethodController::GetInstance()->FinishTextPreview(); + auto ret = InputMethodController::GetInstance()->FinishTextPreview(); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } -ErrCode InputDataChannelServiceImpl::SendMessage(const ArrayBuffer &arraybuffer) +ErrCode InputDataChannelServiceImpl::SendMessage(const ArrayBuffer &arraybuffer, uint64_t msgId) { - return InputMethodController::GetInstance()->RecvMessage(arraybuffer); + auto ret = InputMethodController::GetInstance()->RecvMessage(arraybuffer); + ResponseData data = std::monostate{}; + InputMethodController::GetInstance()->ResponseDataChannel(msgId, ret, data); + return ret; } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index c9009bee9..dd412037f 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -54,6 +54,7 @@ constexpr int32_t LOOP_COUNT = 5; constexpr int32_t LOG_MAX_TIME = 20; constexpr int64_t DELAY_TIME = 100; constexpr int32_t ACE_DEAL_TIME_OUT = 200; +static constexpr int32_t MAX_TIMEOUT = 2500; InputMethodController::InputMethodController() { IMSA_HILOGD("IMC structure."); @@ -273,7 +274,7 @@ int32_t InputMethodController::Attach(sptr listener, cons } IMSA_HILOGI("sessionId_ %{public}u", sessionId_.load()); if (clientInfo_.isNotifyInputStart && lastListener != nullptr) { - lastListener->OnDetach(); + lastListener->OnDetachV2(); } ClearEditorCache(clientInfo_.isNotifyInputStart, lastListener); SetTextListener(listener); @@ -394,7 +395,7 @@ int32_t InputMethodController::Close() auto listener = GetTextListener(); if (listener != nullptr) { - listener->OnDetach(); + listener->OnDetachV2(); } OperateIMEInfoCode infoCode = OperateIMEInfoCode::IME_UNBIND; { @@ -632,7 +633,7 @@ void InputMethodController::OnRemoteSaDied(const wptr &remote) auto textListener = GetTextListener(); if (textListener != nullptr && textConfig_.inputAttribute.isTextPreviewSupported) { IMSA_HILOGD("finish text preview."); - textListener->FinishTextPreview(); + textListener->FinishTextPreviewV2(); } { std::lock_guard lock(abilityLock_); @@ -834,7 +835,7 @@ int32_t InputMethodController::GetLeft(int32_t length, std::u16string &text) int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); { InputMethodSyncTrace aceTracer("ACE_GetForward"); - text = listener->GetLeftTextOfCursor(length); + text = listener->GetLeftTextOfCursorV2(length); } PrintLogIfAceTimeout(start); return ErrorCode::NO_ERROR; @@ -850,7 +851,7 @@ int32_t InputMethodController::GetRight(int32_t length, std::u16string &text) ErrorCode::ERROR_CLIENT_NOT_EDITABLE); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - text = listener->GetRightTextOfCursor(length); + text = listener->GetRightTextOfCursorV2(length); return ErrorCode::NO_ERROR; } @@ -864,7 +865,7 @@ int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index) ErrorCode::ERROR_CLIENT_NOT_EDITABLE); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - index = listener->GetTextIndexAtCursor(); + index = listener->GetTextIndexAtCursorV2(); return ErrorCode::NO_ERROR; } @@ -1110,10 +1111,10 @@ void InputMethodController::OnInputStop(bool isStopInactiveClient) IMSA_HILOGD("listener is not nullptr!"); if (textConfig_.inputAttribute.isTextPreviewSupported) { IMSA_HILOGD("finish text preview."); - listener->FinishTextPreview(); + listener->FinishTextPreviewV2(); } if (!isStopInactiveClient || !listener->IsFromTs()) { - listener->SendKeyboardStatus(KeyboardStatus::HIDE); + listener->SendKeyboardStatusV2(KeyboardStatus::HIDE); } } isBound_.store(false); @@ -1156,7 +1157,7 @@ void InputMethodController::SelectByRange(int32_t start, int32_t end) IMSA_HILOGD("InputMethodController start: %{public}d, end: %{public}d.", start, end); auto listener = GetTextListener(); if (IsEditable() && listener != nullptr) { - listener->HandleSetSelection(start, end); + listener->HandleSetSelectionV2(start, end); } else { IMSA_HILOGE("not editable or textListener_ is nullptr!"); } @@ -1174,7 +1175,7 @@ void InputMethodController::SelectByMovement(int32_t direction, int32_t cursorMo "InputMethodController start, direction: %{public}d, cursorMoveSkip: %{public}d", direction, cursorMoveSkip); auto listener = GetTextListener(); if (IsEditable() && listener != nullptr) { - listener->HandleSelect(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip); + listener->HandleSelectV2(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip); } else { IMSA_HILOGE("not editable or textListener_ is nullptr!"); } @@ -1194,7 +1195,7 @@ int32_t InputMethodController::HandleExtendAction(int32_t action) IMSA_HILOGE("not editable or textListener is nullptr!"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - listener->HandleExtendAction(action); + listener->HandleExtendActionV2(action); return ErrorCode::NO_ERROR; } @@ -1253,7 +1254,7 @@ int32_t InputMethodController::InsertText(const std::u16string &text) { InputMethodSyncTrace aceTracer("ACE_InsertText"); IMSA_HILOGD("ACE InsertText."); - listener->InsertText(text); + listener->InsertTextV2(text); } PrintLogIfAceTimeout(start); @@ -1275,7 +1276,7 @@ int32_t InputMethodController::DeleteForward(int32_t length) { InputMethodSyncTrace aceTracer("ACE_DeleteForward"); // reverse for compatibility - listener->DeleteBackward(length); + listener->DeleteBackwardV2(length); } PrintLogIfAceTimeout(start); return ErrorCode::NO_ERROR; @@ -1292,7 +1293,7 @@ int32_t InputMethodController::DeleteBackward(int32_t length) return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } // reverse for compatibility - listener->DeleteForward(length); + listener->DeleteForwardV2(length); return ErrorCode::NO_ERROR; } @@ -1304,7 +1305,7 @@ int32_t InputMethodController::MoveCursor(Direction direction) IMSA_HILOGE("not editable or textListener_ is nullptr!"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - listener->MoveCursor(direction); + listener->MoveCursorV2(direction); return ErrorCode::NO_ERROR; } @@ -1316,7 +1317,7 @@ void InputMethodController::SendKeyboardStatus(KeyboardStatus status) IMSA_HILOGE("listener is nullptr!"); return; } - listener->SendKeyboardStatus(status); + listener->SendKeyboardStatusV2(status); if (status == KeyboardStatus::HIDE) { std::lock_guard lock(clientInfoLock_); clientInfo_.isShowKeyboard = false; @@ -1339,7 +1340,7 @@ void InputMethodController::NotifyPanelStatusInfo(const PanelStatusInfo &info) } if (info.visible || info.sessionId == 0 || info.sessionId == sessionId_) { - listener->NotifyPanelStatusInfo(info); + listener->NotifyPanelStatusInfoV2(info); } if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD && info.panelInfo.panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN && !info.visible) { @@ -1356,7 +1357,7 @@ void InputMethodController::NotifyKeyboardHeight(uint32_t height) IMSA_HILOGE("listener is nullptr!"); return; } - listener->NotifyKeyboardHeight(height); + listener->NotifyKeyboardHeightV2(height); } int32_t InputMethodController::SendFunctionKey(int32_t functionKey) @@ -1455,7 +1456,7 @@ int32_t InputMethodController::ReceivePrivateCommand( return ErrorCode::ERROR_EX_NULL_POINTER; } IMSA_HILOGD("IMC in."); - auto ret = listener->ReceivePrivateCommand(privateCommand); + auto ret = listener->ReceivePrivateCommandV2(privateCommand); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("ReceivePrivateCommand err, ret: %{public}d!", ret); return ErrorCode::ERROR_TEXT_LISTENER_ERROR; @@ -1517,7 +1518,7 @@ int32_t InputMethodController::SetPreviewTextInner(const std::string &text, cons int64_t start = duration_cast(system_clock::now().time_since_epoch()).count(); { InputMethodSyncTrace aceTracer("ACE_SetPreviewText"); - ret = listener->SetPreviewText(Str8ToStr16(text), range); + ret = listener->SetPreviewTextV2(Str8ToStr16(text), range); } PrintLogIfAceTimeout(start); if (ret != ErrorCode::NO_ERROR) { @@ -1546,7 +1547,7 @@ int32_t InputMethodController::FinishTextPreview() } { InputMethodSyncTrace aceTracer("ACE_FinishTextPreview"); - listener->FinishTextPreview(); + listener->FinishTextPreviewV2(); } return ErrorCode::NO_ERROR; } @@ -1698,5 +1699,337 @@ int32_t InputMethodController::SendPrivateData(const std::unordered_mapSendPrivateData(value); } + +int32_t InputMethodController::ResponseDataChannel(uint64_t msgId, int32_t code, ResponseData &data) +{ + auto agent = GetAgent(); + if (agent == nullptr) { + IMSA_HILOGE("agent is nullptr!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + ResponseDataInner inner = {}; + inner.rspData = data; + return agent->ResponseDataChannel(msgId, code, inner); +} + +void OnTextChangedListener::InsertTextV2(const std::u16string &text) +{ + auto task = [this, text]() { + InsertText(text); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "InsertTextV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} +void OnTextChangedListener::DeleteForwardV2(int32_t length) +{ + auto task = [this, length]() { + DeleteForward(length); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "DeleteForwardV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::DeleteBackwardV2(int32_t length) +{ + auto task = [this, length]() { + DeleteBackward(length); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "DeleteBackwardV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::SendKeyboardStatusV2(const KeyboardStatus &keyboardStatus) +{ + auto task = [this, keyboardStatus]() { + SendKeyboardStatus(keyboardStatus); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "SendKeyboardStatusV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::SendFunctionKeyV2(const FunctionKey &functionKey) +{ + auto task = [this, functionKey]() { + SendFunctionKey(functionKey); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "SendFunctionKeyV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::MoveCursorV2(const Direction direction) +{ + auto task = [this, direction]() { + MoveCursor(direction); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "MoveCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::HandleExtendActionV2(int32_t action) +{ + auto task = [this, action]() { + HandleExtendAction(action); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "HandleExtendActionV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +std::u16string OnTextChangedListener::GetLeftTextOfCursorV2(int32_t number) +{ + std::u16string text; + auto eventHandler = GetEventHandler(); + std::shared_ptr> textResultHandler = nullptr; + if (eventHandler != nullptr) { + textResultHandler = std::make_shared>(MAX_TIMEOUT, -1); + } + auto task = [this, textResultHandler, number, &text]() { + text = GetLeftTextOfCursor(number); + if (textResultHandler != nullptr) { + textResultHandler->SetValue(number); + } + }; + if (eventHandler != nullptr) { + eventHandler->PostTask(task, "GetLeftTextOfCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + if (!textResultHandler->GetValue()) { + IMSA_HILOGW("GetValue timeout"); + } + } else { + task(); + } + return text; +} + +std::u16string OnTextChangedListener::GetRightTextOfCursorV2(int32_t number) +{ + std::u16string text; + auto eventHandler = GetEventHandler(); + std::shared_ptr> textResultHandler = nullptr; + if (eventHandler != nullptr) { + textResultHandler = std::make_shared>(MAX_TIMEOUT, -1); + } + auto task = [this, textResultHandler, number, &text]() { + text = GetRightTextOfCursor(number); + if (textResultHandler != nullptr) { + textResultHandler->SetValue(number); + } + }; + if (eventHandler != nullptr) { + eventHandler->PostTask(task, "GetRightTextOfCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + if (!textResultHandler->GetValue()) { + IMSA_HILOGW("GetValue timeout"); + } + } else { + task(); + } + return text; +} + +int32_t OnTextChangedListener::GetTextIndexAtCursorV2() +{ + int32_t index = -1; + auto eventHandler = GetEventHandler(); + std::shared_ptr> textResultHandler = nullptr; + if (eventHandler != nullptr) { + textResultHandler = std::make_shared>(MAX_TIMEOUT, -1); + } + auto task = [this, textResultHandler, &index]() { + index = GetTextIndexAtCursor(); + if (textResultHandler != nullptr) { + textResultHandler->SetValue(index); + } + }; + if (eventHandler != nullptr) { + eventHandler->PostTask(task, "GetTextIndexAtCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + if (!textResultHandler->GetValue()) { + IMSA_HILOGW("GetValue timeout"); + } + } else { + task(); + } + return index; +} + +void OnTextChangedListener::SendKeyEventFromInputMethodV2(const KeyEvent &event) +{ + auto task = [this, event]() { + SendKeyEventFromInputMethod(event); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "SendKeyEventFromInputMethodV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::NotifyPanelStatusInfoV2(const PanelStatusInfo &info) +{ + auto task = [this, info]() { + NotifyPanelStatusInfo(info); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "NotifyPanelStatusInfoV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::NotifyKeyboardHeightV2(uint32_t height) +{ + auto task = [this, height]() { + NotifyKeyboardHeight(height); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "NotifyKeyboardHeightV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::SetKeyboardStatusV2(bool status) +{ + auto task = [this, status]() { + SetKeyboardStatus(status); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "SetKeyboardStatusV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::HandleSetSelectionV2(int32_t start, int32_t end) +{ + auto task = [this, start, end]() { + HandleSetSelection(start, end); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "HandleSetSelectionV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::HandleSelectV2(int32_t keyCode, int32_t cursorMoveSkip) +{ + auto task = [this, keyCode, cursorMoveSkip]() { + HandleSelect(keyCode, cursorMoveSkip); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "HandleSelectV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +int32_t OnTextChangedListener::ReceivePrivateCommandV2( + const std::unordered_map &privateCommand) +{ + int32_t ret = -1; + auto eventHandler = GetEventHandler(); + std::shared_ptr> textResultHandler = nullptr; + if (eventHandler != nullptr) { + textResultHandler = std::make_shared>(MAX_TIMEOUT, -1); + } + auto task = [this, textResultHandler, privateCommand, &ret]() { + ret = ReceivePrivateCommand(privateCommand); + if (textResultHandler != nullptr) { + textResultHandler->SetValue(ret); + } + }; + if (eventHandler != nullptr) { + eventHandler->PostTask(task, "GetTextIndexAtCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + if (!textResultHandler->GetValue()) { + IMSA_HILOGW("GetValue timeout"); + } + } else { + task(); + } + return ret; +} + +int32_t OnTextChangedListener::SetPreviewTextV2(const std::u16string &text, const Range &range) +{ + int32_t ret = -1; + auto eventHandler = GetEventHandler(); + std::shared_ptr> textResultHandler = nullptr; + if (eventHandler != nullptr) { + textResultHandler = std::make_shared>(MAX_TIMEOUT, -1); + } + auto task = [this, textResultHandler, text, range, &ret]() { + ret = SetPreviewText(text, range); + if (textResultHandler != nullptr) { + textResultHandler->SetValue(ret); + } + }; + if (eventHandler != nullptr) { + eventHandler->PostTask(task, "GetTextIndexAtCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP); + if (!textResultHandler->GetValue()) { + IMSA_HILOGW("GetValue timeout"); + } + } else { + task(); + } + return ret; +} + +void OnTextChangedListener::FinishTextPreviewV2() +{ + auto task = [this]() { + FinishTextPreview(); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "FinishTextPreviewV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} + +void OnTextChangedListener::OnDetachV2() +{ + auto task = [this]() { + OnDetach(); + }; + auto eventHandler = GetEventHandler(); + if (eventHandler) { + eventHandler->PostTask(task, "OnDetachV2", 0, AppExecFwk::EventQueue::Priority::VIP); + } else { + task(); + } +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/src/input_method_utils.cpp b/frameworks/native/inputmethod_controller/src/input_method_utils.cpp index c2a442e6d..b2a0f6258 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_utils.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_utils.cpp @@ -12,7 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include "input_method_utils.h" +#include "input_method_tools.h" namespace OHOS { namespace MiscServices { @@ -320,5 +323,70 @@ bool ArrayBuffer::Marshalling(Parcel &out) const } return true; } + +bool ResponseDataInner::ReadFromParcel(Parcel &in) +{ + uint64_t index = in.ReadUint64(); + switch (index) { + case static_cast(ResponseDataType::NALL_TYPE): + rspData = std::monostate{}; + break; + case static_cast(ResponseDataType::STRING_TYPE): + rspData = in.ReadString(); + break; + case static_cast(ResponseDataType::INT32_TYPE): + rspData = in.ReadInt32(); + break; + case static_cast(ResponseDataType::CONFIG_TYPE): { + TextTotalConfigInner *config = TextTotalConfigInner::Unmarshalling(in); + if (config == nullptr) { + IMSA_HILOGE("TextTotalConfigInner::Unmarshal is NULL"); + return false; + } + rspData = InputMethodTools::GetInstance().InnerToTextTotalConfig(*config); + delete config; + config = nullptr; + break; + } + default: + IMSA_HILOGE("bad parameter indxe: %{public}" PRIu64 "", index); + return false; + } + return true; +} + +bool ResponseDataInner::Marshalling(Parcel &out) const +{ + uint64_t index = static_cast(rspData.index()); + if (!out.WriteUint64(index)) { + return false; + } + switch (index) { + case static_cast(ResponseDataType::NALL_TYPE): + return true; + case static_cast(ResponseDataType::STRING_TYPE): { + if (!std::holds_alternative(rspData)) { + return false; + } + return out.WriteString(std::get(rspData)); + } + case static_cast(ResponseDataType::INT32_TYPE): { + if (!std::holds_alternative(rspData)) { + return false; + } + return out.WriteInt32(std::get(rspData)); + } + case static_cast(ResponseDataType::CONFIG_TYPE): { + if (!std::holds_alternative(rspData)) { + return false; + } + TextTotalConfigInner textConfigInner = + InputMethodTools::GetInstance().TextTotalConfigToInner(std::get(rspData)); + return textConfigInner.Marshalling(out); + } + default: + return false; + } +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/ndk/BUILD.gn b/frameworks/ndk/BUILD.gn index e656a38d5..f28944ba1 100644 --- a/frameworks/ndk/BUILD.gn +++ b/frameworks/ndk/BUILD.gn @@ -24,6 +24,8 @@ ohos_shared_library("ohinputmethod") { output_extension = "so" sources = [ + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_client_info.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_tools.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_utils.cpp", "src/inputmethod_attach_options_capi.cpp", "src/inputmethod_controller_capi.cpp", diff --git a/frameworks/ndk/src/native_capi_utils.cpp b/frameworks/ndk/src/native_capi_utils.cpp index 7b5412133..3b7eca234 100644 --- a/frameworks/ndk/src/native_capi_utils.cpp +++ b/frameworks/ndk/src/native_capi_utils.cpp @@ -71,6 +71,8 @@ static const std::map ERROR_CODE_MAP = { { ErrorCode::ERROR_IMSA_IME_START_MORE_THAN_EIGHT_SECOND, IME_ERR_IMMS }, { ErrorCode::ERROR_IMSA_FORCE_STOP_IME_TIMEOUT, IME_ERR_IMMS }, { ErrorCode::ERROR_IMC_NULLPTR, IME_ERR_IMMS }, + { ErrorCode::ERROR_RESPONSE_TIMEOUT, IME_ERR_IMCLIENT }, + { ErrorCode::ERROR_TOO_MANY_UNANSWERED_MESSAGE, IME_ERR_IMCLIENT }, }; InputMethod_ErrorCode ErrorCodeConvert(int32_t code) diff --git a/interfaces/inner_api/inputmethod_ability/BUILD.gn b/interfaces/inner_api/inputmethod_ability/BUILD.gn index 5c4e7262a..e639db172 100644 --- a/interfaces/inner_api/inputmethod_ability/BUILD.gn +++ b/interfaces/inner_api/inputmethod_ability/BUILD.gn @@ -322,6 +322,7 @@ ohos_shared_library("inputmethod_ability") { "${inputmethod_path}/frameworks/native/inputmethod_ability/src/tasks/task.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/window_change_listener_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_client_info.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_tools.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_utils.cpp", "${inputmethod_path}/services/src/sys_cfg_parser.cpp", @@ -453,6 +454,7 @@ ohos_static_library("inputmethod_ability_static") { "${inputmethod_path}/frameworks/native/inputmethod_ability/src/tasks/task.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/window_change_listener_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_client_info.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_data_channel_proxy_wrap.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_tools.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/input_method_utils.cpp", "${inputmethod_path}/services/src/sys_cfg_parser.cpp", diff --git a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h index b14b45adb..11f89ec15 100644 --- a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h +++ b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h @@ -115,6 +115,32 @@ public: { return false; } + virtual std::shared_ptr GetEventHandler() const + { + return nullptr; + } + + void InsertTextV2(const std::u16string &text); + void DeleteForwardV2(int32_t length); + void DeleteBackwardV2(int32_t length); + void SendKeyboardStatusV2(const KeyboardStatus &keyboardStatus); + void SendFunctionKeyV2(const FunctionKey &functionKey); + void MoveCursorV2(const Direction direction); + void HandleExtendActionV2(int32_t action); + std::u16string GetLeftTextOfCursorV2(int32_t number); + std::u16string GetRightTextOfCursorV2(int32_t number); + int32_t GetTextIndexAtCursorV2(); + + void SendKeyEventFromInputMethodV2(const KeyEvent &event); + void NotifyPanelStatusInfoV2(const PanelStatusInfo &info); + void NotifyKeyboardHeightV2(uint32_t height); + void SetKeyboardStatusV2(bool status); + void HandleSetSelectionV2(int32_t start, int32_t end); + void HandleSelectV2(int32_t keyCode, int32_t cursorMoveSkip); + int32_t ReceivePrivateCommandV2(const std::unordered_map &privateCommand); + int32_t SetPreviewTextV2(const std::u16string &text, const Range &range); + void FinishTextPreviewV2(); + void OnDetachV2(); }; using PrivateDataValue = std::variant; using KeyEventCallback = std::function &keyEvent, bool isConsumed)>; @@ -957,6 +983,9 @@ private: int32_t ShowTextInputInner(const AttachOptions &attachOptions, ClientType type); int32_t ShowSoftKeyboardInner(ClientType type); void ReportClientShow(int32_t eventCode, int32_t errCode, ClientType type); + int32_t ResponseDataChannel(uint64_t msgId, int32_t code, ResponseData &data); + + friend class InputDataChannelServiceImpl; std::shared_ptr controllerListener_; std::mutex abilityLock_; diff --git a/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp b/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp index 872971f1e..00f696b92 100644 --- a/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp @@ -46,7 +46,7 @@ public: void TearDown() { } static void ResetMemberVar() { - inputMethodAbility_->dataChannelProxy_ = nullptr; + inputMethodAbility_->dataChannelProxyWrap_ = nullptr; inputMethodAbility_->dataChannelObject_ = nullptr; inputMethodAbility_->imeListener_ = nullptr; inputMethodAbility_->panels_.Clear(); diff --git a/test/unittest/cpp_test/src/input_method_ability_test.cpp b/test/unittest/cpp_test/src/input_method_ability_test.cpp index 57c46241c..3e0cfd24f 100644 --- a/test/unittest/cpp_test/src/input_method_ability_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_test.cpp @@ -595,6 +595,7 @@ HWTEST_F(InputMethodAbilityTest, testGetTextConfig, TestSize.Level0) ret = InputMethodAbilityInterface::GetInstance().GetInputAttribute(inputAttribute); EXPECT_EQ(ret, ErrorCode::NO_ERROR); EXPECT_EQ(inputAttribute, textConfig.inputAttribute); + std::this_thread::sleep_for(std::chrono::seconds(2)); } /** @@ -612,6 +613,7 @@ HWTEST_F(InputMethodAbilityTest, testSelectByRange_001, TestSize.Level0) auto ret = inputMethodAbility_->SelectByRange(start, end); EXPECT_EQ(ret, ErrorCode::NO_ERROR); EXPECT_TRUE(TextListener::WaitHandleSetSelection(start, end)); + std::this_thread::sleep_for(std::chrono::seconds(2)); } /** -- Gitee