From 51154770ed2be899dde9ce5b5536787f48bf9e84 Mon Sep 17 00:00:00 2001 From: zhouyongfei Date: Sat, 12 Feb 2022 14:40:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=8E=B7=E5=8F=96=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E6=B3=95=E5=88=97=E8=A1=A8=E5=92=8C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E8=BE=93=E5=85=A5=E6=B3=95=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhouyongfei --- BUILD.gn | 3 + etc/para/BUILD.gn | 42 +++++ etc/para/include/para_handle.h | 33 ++++ etc/para/inputmethod.para | 14 ++ etc/para/src/para_handle.cpp | 36 ++++ .../include/input_method_controller.h | 2 + .../input_method_system_ability_proxy.h | 1 + .../src/input_method_controller.cpp | 24 +++ .../src/input_method_system_ability_proxy.cpp | 18 ++ .../js/declaration/api/@ohos.inputmethod.d.ts | 42 +++++ interfaces/kits/js/napi/BUILD.gn | 58 ++++++- .../kits/js/napi/include/js_input_method.h | 30 ++++ .../kits/js/napi/src/input_method_module.cpp | 29 ++++ .../kits/js/napi/src/js_input_method.cpp | 136 +++++++++++++++ services/BUILD.gn | 2 + services/dialog/js/pages/index/index.hml | 4 +- .../include/i_input_method_system_ability.h | 2 + .../include/input_method_system_ability.h | 9 +- .../input_method_system_ability_stub.h | 2 + services/include/message_handler.h | 1 + services/src/input_method_system_ability.cpp | 161 +++++++++++++++--- .../src/input_method_system_ability_stub.cpp | 24 ++- 22 files changed, 648 insertions(+), 25 deletions(-) create mode 100644 etc/para/BUILD.gn create mode 100644 etc/para/include/para_handle.h create mode 100644 etc/para/inputmethod.para create mode 100644 etc/para/src/para_handle.cpp create mode 100644 interfaces/kits/js/declaration/api/@ohos.inputmethod.d.ts create mode 100644 interfaces/kits/js/napi/include/js_input_method.h create mode 100644 interfaces/kits/js/napi/src/input_method_module.cpp create mode 100644 interfaces/kits/js/napi/src/js_input_method.cpp diff --git a/BUILD.gn b/BUILD.gn index 7203b1b..bf070ce 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -19,9 +19,12 @@ group("inputmethod_native_packages") { if (is_standard_system) { deps = [ "etc/init:inputmethodservice.cfg", + "etc/para:inputmethod.para", + "etc/para:inputmethod_para", "frameworks/inputmethod_ability:inputmethod_ability", "frameworks/inputmethod_controller:inputmethod_client", "interfaces/kits/js/declaration:inputmethod", + "interfaces/kits/js/napi:inputmethod", "interfaces/kits/js/napi:inputmethodengine", "profile:miscservices_inputmethod_sa_profiles", "services:inputmethod_service", diff --git a/etc/para/BUILD.gn b/etc/para/BUILD.gn new file mode 100644 index 0000000..4f8f3f2 --- /dev/null +++ b/etc/para/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (C) 2022 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. + +import("//base/miscservices/inputmethod/inputmethod.gni") +import("//build/ohos.gni") + +config("inputmethod_para_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} +config("inputmethod_para_public_config") { + visibility = [] + include_dirs = [ "include" ] +} +ohos_shared_library("inputmethod_para") { + sources = [ "src/para_handle.cpp" ] + configs = [ ":inputmethod_para_config" ] + deps = [] + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "startup_l2:syspara", + ] + public_configs = [ ":inputmethod_para_public_config" ] + subsystem_name = "miscservices" + part_name = "inputmethod_native" +} + +ohos_prebuilt_etc("inputmethod.para") { + source = "//base/miscservices/inputmethod/etc/para/inputmethod.para" + part_name = "inputmethod_native" + module_install_dir = "etc/param" +} diff --git a/etc/para/include/para_handle.h b/etc/para/include/para_handle.h new file mode 100644 index 0000000..8b58009 --- /dev/null +++ b/etc/para/include/para_handle.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 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 OHOS_MISCSERVICES_INPUTMETHOD_PARA_HANDLE_H +#define OHOS_MISCSERVICES_INPUTMETHOD_PARA_HANDLE_H +#include +namespace OHOS { + namespace MiscServices { + class ParaHandle { + public: + ParaHandle() = default; + virtual ~ParaHandle() = default; + static bool SetDefaultIme(const std::string &imeName); + static std::string GetDefaultIme(); + private: + static const char *DEFAULT_IME; + static constexpr int CONFIG_LEN = 128; + }; + } +} +#endif // OHOS_MISCSERVICES_INPUTMETHOD_PARA_HANDLE_H diff --git a/etc/para/inputmethod.para b/etc/para/inputmethod.para new file mode 100644 index 0000000..6a7b185 --- /dev/null +++ b/etc/para/inputmethod.para @@ -0,0 +1,14 @@ +# Copyright (C) 2022 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. + +persist.sys.default_ime=com.example.kikakeyboard/com.example.kikakeyboard.ServiceExtAbility \ No newline at end of file diff --git a/etc/para/src/para_handle.cpp b/etc/para/src/para_handle.cpp new file mode 100644 index 0000000..0aeff9c --- /dev/null +++ b/etc/para/src/para_handle.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 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 "para_handle.h" +#include "parameter.h" + +namespace OHOS { + namespace MiscServices { + const char *ParaHandle::DEFAULT_IME = "persist.sys.default_ime"; + bool ParaHandle::SetDefaultIme(const std::string &imeName) + { + return SetParameter(DEFAULT_IME, imeName.data()) == 0; + } + + std::string ParaHandle::GetDefaultIme() + { + char value[CONFIG_LEN]; + int code = GetParameter(DEFAULT_IME, "", value, CONFIG_LEN); + if (code > 0) { + return value; + } + return ""; + } + } +} diff --git a/frameworks/inputmethod_controller/include/input_method_controller.h b/frameworks/inputmethod_controller/include/input_method_controller.h index 4dd4ca2..78cdfed 100644 --- a/frameworks/inputmethod_controller/include/input_method_controller.h +++ b/frameworks/inputmethod_controller/include/input_method_controller.h @@ -66,6 +66,8 @@ namespace MiscServices { void OnSelectionChange(std::u16string text, int start, int end); void OnConfigurationChange(Configuration info); bool dispatchKeyEvent(std::shared_ptr keyEvent); + void DisplayOptionalInputMethod(); + std::vector ListInputMethod(); private: InputMethodController(); ~InputMethodController(); diff --git a/frameworks/inputmethod_controller/include/input_method_system_ability_proxy.h b/frameworks/inputmethod_controller/include/input_method_system_ability_proxy.h index 491a21c..a20901c 100644 --- a/frameworks/inputmethod_controller/include/input_method_system_ability_proxy.h +++ b/frameworks/inputmethod_controller/include/input_method_system_ability_proxy.h @@ -48,6 +48,7 @@ namespace MiscServices { int32_t Start(sptr &client); int32_t Stop(sptr &client); + virtual void displayOptionalInputMethod(MessageParcel& data) override; virtual int32_t getDisplayMode(int32_t retMode) override; virtual int32_t getKeyboardWindowHeight(int32_t retHeight) override; virtual int32_t getCurrentKeyboardType(KeyboardType *retType) override; diff --git a/frameworks/inputmethod_controller/src/input_method_controller.cpp b/frameworks/inputmethod_controller/src/input_method_controller.cpp index 6c2087c..05bb100 100644 --- a/frameworks/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/inputmethod_controller/src/input_method_controller.cpp @@ -232,6 +232,30 @@ using namespace MessageID; mImms->prepareInput(data); } + void InputMethodController::DisplayOptionalInputMethod() + { + IMSA_HILOGI("InputMethodController::DisplayOptionalInputMethod"); + if (mImms == nullptr) { + return; + } + MessageParcel data; + if (!(data.WriteInterfaceToken(mImms->GetDescriptor()))) { + return; + } + mImms->displayOptionalInputMethod(data); + } + + std::vector InputMethodController::ListInputMethod() + { + IMSA_HILOGI("InputMethodController::listInputMethod"); + std::vector properties; + if (mImms == nullptr) { + return properties; + } + mImms->listInputMethod(&properties); + return properties; + } + void InputMethodController::StartInput(sptr &client) { IMSA_HILOGI("InputMethodController::StartInput"); diff --git a/frameworks/inputmethod_controller/src/input_method_system_ability_proxy.cpp b/frameworks/inputmethod_controller/src/input_method_system_ability_proxy.cpp index 5d63719..4b8bd01 100644 --- a/frameworks/inputmethod_controller/src/input_method_system_ability_proxy.cpp +++ b/frameworks/inputmethod_controller/src/input_method_system_ability_proxy.cpp @@ -41,6 +41,24 @@ namespace MiscServices { } } + void InputMethodSystemAbilityProxy::displayOptionalInputMethod(MessageParcel& data) + { + MessageParcel reply; + MessageOption option; + + auto ret = Remote()->SendRequest(DISPLAY_OPTIONAL_INPUT_METHOD, data, reply, option); + if (ret != NO_ERROR) { + IMSA_HILOGI("InputMethodSystemAbilityProxy::displayOptionalInputMethod SendRequest failed"); + return; + } + + ret = reply.ReadInt32(); + if (ret != NO_ERROR) { + IMSA_HILOGI("InputMethodSystemAbilityProxy::displayOptionalInputMethod reply failed"); + return; + } + } + void InputMethodSystemAbilityProxy::releaseInput(MessageParcel& data) { MessageParcel reply; diff --git a/interfaces/kits/js/declaration/api/@ohos.inputmethod.d.ts b/interfaces/kits/js/declaration/api/@ohos.inputmethod.d.ts new file mode 100644 index 0000000..c8c5eac --- /dev/null +++ b/interfaces/kits/js/declaration/api/@ohos.inputmethod.d.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 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. + */ + +import {AsyncCallback} from './basic'; + +/** + * inputmethod + * + * @since 8 + * @devices phone, tablet, tv, wearable + */ +declare namespace inputMethod { + + function getInputMethodSetting(): InputMethodSetting; + + interface InputMethodSetting { + listInputMethod(callback: AsyncCallback>): void; + listInputMethod(): Promise>; + + displayOptionalInputMethod(callback: AsyncCallback): void; + displayOptionalInputMethod(): Promise; + } + + interface InputMethodProperty { + readonly packageName: string; + readonly methodId: string; + } +} + +export default inputMethod; diff --git a/interfaces/kits/js/napi/BUILD.gn b/interfaces/kits/js/napi/BUILD.gn index 72bc6b1..eb1a433 100644 --- a/interfaces/kits/js/napi/BUILD.gn +++ b/interfaces/kits/js/napi/BUILD.gn @@ -10,7 +10,7 @@ # 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. - +import("//base/miscservices/inputmethod/inputmethod.gni") import("//build/ohos.gni") config("inputmethodengine_native_config") { @@ -23,6 +23,16 @@ config("inputmethodengine_native_public_config") { include_dirs = [ "include" ] } +config("inputmethod_native_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +config("inputmethod_native_public_config") { + visibility = [] + include_dirs = [ "include" ] +} + ohos_shared_library("inputmethodengine") { sources = [ "src/input_method_engine_module.cpp", @@ -66,3 +76,49 @@ ohos_shared_library("inputmethodengine") { subsystem_name = "miscservices" part_name = "inputmethod_native" } + +ohos_shared_library("inputmethod") { + sources = [ + "${inputmethod_path}/frameworks/inputmethod_controller/src/input_client_stub.cpp", + "${inputmethod_path}/frameworks/inputmethod_controller/src/input_data_channel_stub.cpp", + "${inputmethod_path}/frameworks/inputmethod_controller/src/input_method_controller.cpp", + "src/input_method_module.cpp", + "src/js_input_method.cpp", + ] + + configs = [ ":inputmethod_native_config" ] + + deps = [ + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//base/miscservices/inputmethod/frameworks/inputmethod_ability:inputmethod_ability", + "//base/miscservices/inputmethod/services:inputmethod_service", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/app_manager:app_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/intent:intent", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/ace/napi/:ace_napi", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core", + "//foundation/communication/ipc/interfaces/innerkits/ipc_single:ipc_single", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//utils/native/base:utils", + ] + + external_deps = [ + "ability_runtime:runtime", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + public_configs = [ ":inputmethod_native_public_config" ] + + relative_install_dir = "module" + subsystem_name = "miscservices" + part_name = "inputmethod_native" +} diff --git a/interfaces/kits/js/napi/include/js_input_method.h b/interfaces/kits/js/napi/include/js_input_method.h new file mode 100644 index 0000000..0ed3184 --- /dev/null +++ b/interfaces/kits/js/napi/include/js_input_method.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 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 OHOS_MISCSERVICES_JS_INPUT_METHOD_ENGINE_H +#define OHOS_MISCSERVICES_JS_INPUT_METHOD_ENGINE_H + +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "global.h" +#include "js_runtime_utils.h" + +namespace OHOS { + namespace MiscServices { + NativeValue* JsInputMethodInit(NativeEngine* engine, NativeValue* exportObj); + } +} + +#endif // OHOS_MISCSERVICES_JS_INPUT_METHOD_ENGINE_H \ No newline at end of file diff --git a/interfaces/kits/js/napi/src/input_method_module.cpp b/interfaces/kits/js/napi/src/input_method_module.cpp new file mode 100644 index 0000000..50e65a8 --- /dev/null +++ b/interfaces/kits/js/napi/src/input_method_module.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 "native_engine/native_engine.h" +#include "js_input_method.h" + +extern "C" __attribute__((constructor)) void NAPI_inputMethod_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "inputMethod", + .fileName = "inputmethod.so/inputmethod.js", + .registerCallback = OHOS::MiscServices::JsInputMethodInit, + }; + + moduleManager->Register(&newModuleInfo); +} \ No newline at end of file diff --git a/interfaces/kits/js/napi/src/js_input_method.cpp b/interfaces/kits/js/napi/src/js_input_method.cpp new file mode 100644 index 0000000..7b931f9 --- /dev/null +++ b/interfaces/kits/js/napi/src/js_input_method.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2021 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 "js_input_method.h" +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "string_ex.h" +#include "input_method_utils.h" +#include "event_handler.h" +#include "event_runner.h" +#include "input_method_controller.h" + +namespace OHOS { +namespace MiscServices { + namespace { + constexpr size_t ARGC_ZERO = 0; + } + class JsInputMethod { + public: + explicit JsInputMethod(NativeEngine* engine) + { + IMSA_HILOGI("JsInputMethod::Constructor is called"); + } + + ~JsInputMethod() = default; + + static void Finalizer(NativeEngine* engine, void* data, void* hint) + { + IMSA_HILOGI("JsInputMethod::Finalizer is called"); + std::unique_ptr(static_cast(data)); + } + + static NativeValue* GetInputMethodSetting(NativeEngine* engine, NativeCallbackInfo* info) + { + IMSA_HILOGI("JsInputMethod::GetInputMethodSetting is called"); + JsInputMethod* me = AbilityRuntime::CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetInputMethodSetting(*engine, *info) : nullptr; + } + + static NativeValue* DisplayOptionalInputMethod(NativeEngine* engine, NativeCallbackInfo* info) + { + IMSA_HILOGI("JsInputMethod::DisplayOptionalInputMethod is called"); + if (info->argc != ARGC_ZERO) { + IMSA_HILOGI("JsInputMethod::OnDisplayOptionalInputMethod has params, return!"); + return engine->CreateUndefined(); + } + + InputMethodController::GetInstance()->DisplayOptionalInputMethod(); + + return engine->CreateUndefined(); + } + + static NativeValue* ListInputMethod(NativeEngine* engine, NativeCallbackInfo* info) + { + IMSA_HILOGI("JsInputMethod::ListInputMethod is called"); + if (info->argc != ARGC_ZERO) { + IMSA_HILOGI("JsInputMethod::ListInputMethod has params, return!"); + return engine->CreateUndefined(); + } + + std::vector properties = InputMethodController::GetInstance()->ListInputMethod(); + if (properties.size() == 0) { + IMSA_HILOGI("JsInputMethod::ListInputMethod has no ime"); + return engine->CreateUndefined(); + } + NativeValue* arrayValue = engine->CreateArray(properties.size()); + NativeArray* array = AbilityRuntime::ConvertNativeValueTo(arrayValue); + uint32_t index = 0; + for (const auto &info : properties) { + NativeValue* objValue = engine->CreateObject(); + NativeObject* object = AbilityRuntime::ConvertNativeValueTo(objValue); + + IMSA_HILOGI("JsInputMethod::ListInputMethod %{public}s/%{public}s", Str16ToStr8(info->mPackageName).c_str(), Str16ToStr8(info->mAbilityName).c_str()); + + object->SetProperty("packageName", AbilityRuntime::CreateJsValue(*engine, Str16ToStr8(info->mPackageName))); + object->SetProperty("methodId", AbilityRuntime::CreateJsValue(*engine, Str16ToStr8(info->mAbilityName))); + array->SetElement(index++, objValue); + } + + return arrayValue; + } + private: + NativeValue* OnGetInputMethodSetting(NativeEngine& engine, NativeCallbackInfo& info) + { + IMSA_HILOGI("JsInputMethod::OnGetInputMethodSetting is called!"); + + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = AbilityRuntime::ConvertNativeValueTo(objValue); + + AbilityRuntime::BindNativeFunction(engine, *object, "displayOptionalInputMethod", + JsInputMethod::DisplayOptionalInputMethod); + AbilityRuntime::BindNativeFunction(engine, *object, "listInputMethod", JsInputMethod::ListInputMethod); + + return objValue; + } + }; + + NativeValue* JsInputMethodInit(NativeEngine* engine, NativeValue* exportObj) + { + IMSA_HILOGI("JsInputMethodInit() is called!"); + + if (engine == nullptr || exportObj == nullptr) { + IMSA_HILOGI("engine or exportObj null"); + return nullptr; + } + + NativeObject* object = AbilityRuntime::ConvertNativeValueTo(exportObj); + if (object == nullptr) { + IMSA_HILOGI("object null"); + return nullptr; + } + + std::unique_ptr jsInputMethod = std::make_unique(engine); + object->SetNativePointer(jsInputMethod.release(), JsInputMethod::Finalizer, nullptr); + + // create inputMethod + AbilityRuntime::BindNativeFunction(*engine, *object, "getInputMethodSetting", + JsInputMethod::GetInputMethodSetting); + + return engine->CreateUndefined(); + } +} +} \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index 3c8095a..7d63149 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -52,6 +52,7 @@ ohos_shared_library("inputmethod_service") { deps = [ "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//base/miscservices/inputmethod/etc/para:inputmethod_para", "//base/miscservices/inputmethod/frameworks/inputmethod_ability:inputmethod_ability", "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", "//foundation/aafwk/standard/interfaces/innerkits/app_manager:app_manager", @@ -59,6 +60,7 @@ ohos_shared_library("inputmethod_service") { "//foundation/aafwk/standard/interfaces/innerkits/intent:intent", "//foundation/aafwk/standard/interfaces/innerkits/want:want", "//foundation/aafwk/standard/services/abilitymgr:abilityms", + "//foundation/ace/ace_engine/interfaces/innerkits/ui_service_manager:ui_service_mgr", "//foundation/ace/napi/:ace_napi", "//foundation/ace/napi/:ace_napi", "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", diff --git a/services/dialog/js/pages/index/index.hml b/services/dialog/js/pages/index/index.hml index 1b3c834..c99691b 100644 --- a/services/dialog/js/pages/index/index.hml +++ b/services/dialog/js/pages/index/index.hml @@ -9,10 +9,10 @@ {{ $item.name }} {{ $item.discription }} - - diff --git a/services/include/i_input_method_system_ability.h b/services/include/i_input_method_system_ability.h index 1a35777..8274570 100644 --- a/services/include/i_input_method_system_ability.h +++ b/services/include/i_input_method_system_ability.h @@ -45,6 +45,7 @@ namespace MiscServices { LIST_INPUT_METHOD, LIST_KEYBOARD_TYPE, SET_CORE_AND_AGENT, + DISPLAY_OPTIONAL_INPUT_METHOD, }; DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.inputmethod.IInputMethodSystemAbility"); @@ -55,6 +56,7 @@ namespace MiscServices { virtual void stopInput(MessageParcel& data) = 0; virtual void SetCoreAndAgent(MessageParcel& data) = 0; + virtual void displayOptionalInputMethod(MessageParcel& data) = 0; virtual int32_t getDisplayMode(int32_t retMode) = 0; virtual int32_t getKeyboardWindowHeight(int32_t retHeight) = 0; virtual int32_t getCurrentKeyboardType(KeyboardType *retType) = 0; diff --git a/services/include/input_method_system_ability.h b/services/include/input_method_system_ability.h index 4ddd6f0..1b31c24 100644 --- a/services/include/input_method_system_ability.h +++ b/services/include/input_method_system_ability.h @@ -23,6 +23,8 @@ #include "peruser_setting.h" #include "peruser_session.h" #include "event_handler.h" +#include "bundle_mgr_proxy.h" +#include "ability_manager_interface.h" namespace OHOS { namespace MiscServices { @@ -50,6 +52,7 @@ namespace MiscServices { virtual int32_t getCurrentKeyboardType(KeyboardType *retType) override; virtual int32_t listInputMethodEnabled(std::vector *properties) override; virtual int32_t listInputMethod(std::vector *properties) override; + virtual int32_t listInputMethodByUserId(int32_t userId, std::vector *properties) override; virtual int32_t listKeyboardType(const std::u16string& imeId, std::vector *types) override; protected: void OnStart() override; @@ -68,7 +71,8 @@ namespace MiscServices { void WorkThread(); PerUserSetting *GetUserSetting(int32_t userId); PerUserSession *GetUserSession(int32_t userId); - void StartInputService(); + void StartInputService(std::string imeId); + void StopInputService(std::string imeId); int32_t OnUserStarted(const Message *msg); int32_t OnUserStopped(const Message *msg); int32_t OnUserUnlocked(const Message *msg); @@ -80,6 +84,9 @@ namespace MiscServices { int32_t OnPackageAdded(const Message *msg); int32_t OnDisableIms(const Message *msg); int32_t OnAdvanceToNext(const Message *msg); + void OnDisplayOptionalInputMethod(int32_t userId); + static sptr GetAbilityManagerService(); + OHOS::sptr GetBundleMgr(); ServiceRunningState state_; void InitServiceHandler(); diff --git a/services/include/input_method_system_ability_stub.h b/services/include/input_method_system_ability_stub.h index 6366ce0..96db418 100644 --- a/services/include/input_method_system_ability_stub.h +++ b/services/include/input_method_system_ability_stub.h @@ -34,6 +34,8 @@ namespace MiscServices { virtual void startInput(MessageParcel& data) override; virtual void stopInput(MessageParcel& data) override; virtual void SetCoreAndAgent(MessageParcel& data) override; + virtual void displayOptionalInputMethod(MessageParcel& data) override; + virtual int32_t listInputMethodByUserId(int32_t userId, std::vector *properties) = 0; protected: int32_t getUserId(int32_t uid); int USER_ID_CHANGE_VALUE = 200000; // user range diff --git a/services/include/message_handler.h b/services/include/message_handler.h index b7ec9fe..d5a41ce 100644 --- a/services/include/message_handler.h +++ b/services/include/message_handler.h @@ -52,6 +52,7 @@ namespace MessageID { MSG_ID_DISABLE_IMS, // disable input method service MSG_ID_RESTART_IMS, // restart input method service MSG_ID_HIDE_KEYBOARD_SELF, // hide the current keyboard + MSG_ID_DISPLAY_OPTIONAL_INPUT_METHOD, MSG_ID_ADVANCE_TO_NEXT, // switch to next MSG_ID_SET_DISPLAY_MODE, // set display mode diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index 51491dc..c4ea21e 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -20,6 +20,14 @@ #include "iservice_registry.h" #include "ipc_skeleton.h" #include "global.h" +#include "wm_common.h" +#include "ui_service_mgr_client.h" +#include "bundle_mgr_proxy.h" +#include "para_handle.h" +#include "ability_manager_interface.h" +#include "ability_connect_callback_proxy.h" +#include "sa_mgr_client.h" +#include "application_info.h" namespace OHOS { namespace MiscServices { @@ -124,7 +132,8 @@ namespace MiscServices { } IMSA_HILOGI("Publish ErrorCode::NO_ERROR."); state_ = ServiceRunningState::STATE_RUNNING; - StartInputService(); + std::string defaultIme = ParaHandle::GetDefaultIme(); + StartInputService(defaultIme); return ErrorCode::NO_ERROR; } @@ -171,8 +180,9 @@ namespace MiscServices { setting->Initialize(); } - void InputMethodSystemAbility::StartInputService() { - IMSA_HILOGE("InputMethodSystemAbility::StartInputService()"); + void InputMethodSystemAbility::StartInputService(std::string imeId) { + IMSA_HILOGE("InputMethodSystemAbility::StartInputService() ime:%{public}s", imeId.c_str()); + PerUserSession *session = GetUserSession(MAIN_USER_ID); std::map::const_iterator it = msgHandlers.find(MAIN_USER_ID); @@ -186,13 +196,32 @@ namespace MiscServices { msgHandlers.insert(std::pair(MAIN_USER_ID, handler)); } - if (!session->StartInputService()) { + bool isStartSuccess = false; + sptr ams = GetAbilityManagerService(); + if (ams != nullptr) { + AAFwk::Want want; + want.SetAction("action.system.inputmethod"); + std::string::size_type pos = imeId.find("/"); + want.SetElementName(imeId.substr(0, pos), imeId.substr(pos + 1)); + int32_t result = ams->StartAbility(want); + if (result != 0) { + IMSA_HILOGE("PerUserSession::StartInputService fail. result = %{public}d", result); + isStartSuccess = false; + } + isStartSuccess = true; + } + + if (!isStartSuccess) { IMSA_HILOGE("StartInputService failed. Try again 10s later"); - auto callback = [=]() { StartInputService(); }; + auto callback = [this, imeId]() { StartInputService(imeId); }; serviceHandler_->PostTask(callback, INIT_INTERVAL); } } + void InputMethodSystemAbility::StopInputService(std::string imeId) { + IMSA_HILOGE("InputMethodSystemAbility::StopInputService(%{public}s)", imeId.c_str()); + } + /*! Get the state of user \n This API is added for unit test. \param userID the id of given user @@ -320,29 +349,31 @@ namespace MiscServices { return ErrorCode::NO_ERROR; } + int32_t InputMethodSystemAbility::listInputMethod(std::vector *properties) + { + return ErrorCode::NO_ERROR; + } + /*! Get all of the input method engine list installed in the system \n Run in binder thread \param[out] properties input method engine list returned to the caller \return ErrorCode::NO_ERROR no error \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked */ - int32_t InputMethodSystemAbility::listInputMethod(std::vector *properties) + int32_t InputMethodSystemAbility::listInputMethodByUserId(int32_t userId, std::vector *properties) { - int32_t uid = IPCSkeleton::GetCallingUid(); - int32_t userId = getUserId(uid); - PerUserSetting *setting = GetUserSetting(userId); - if (setting == nullptr || setting->GetUserState() != UserState::USER_STATE_UNLOCKED) { - IMSA_HILOGE("%s %d\n", ErrorCode::ToString(ErrorCode::ERROR_USER_NOT_UNLOCKED), userId); - return ErrorCode::ERROR_USER_NOT_UNLOCKED; + IMSA_HILOGI("InputMethodSystemAbility::listInputMethodByUserId"); + std::vector extensionInfos; + bool ret = GetBundleMgr()->QueryExtensionAbilityInfos(AppExecFwk::ExtensionAbilityType::SERVICE, userId, extensionInfos); + if (!ret) { + IMSA_HILOGI("InputMethodSystemAbility::ListInputMethod QueryExtensionAbilityInfos error"); + return ErrorCode::ERROR_STATUS_UNKNOWN_ERROR; } - setting->ListInputMethod(properties); - std::vector::iterator it; - for (it = properties->begin(); it != properties->end();) { - if (*it && (*it)->isSystemIme) { - it = properties->erase(it); - } else { - ++it; - } + for (auto extension : extensionInfos) { + InputMethodProperty *property = new InputMethodProperty(); + property->mPackageName = Str8ToStr16(extension.bundleName); + property->mAbilityName = Str8ToStr16(extension.name); + properties->push_back(property); } return ErrorCode::NO_ERROR; } @@ -430,6 +461,12 @@ namespace MiscServices { OnSettingChanged(msg); break; } + case MSG_ID_DISPLAY_OPTIONAL_INPUT_METHOD: { + MessageParcel *data = msg->msgContent_; + int32_t userId = data->ReadInt32(); + OnDisplayOptionalInputMethod(userId); + break; + } case MSG_ID_PREPARE_INPUT: case MSG_ID_RELEASE_INPUT: case MSG_ID_START_INPUT: @@ -777,6 +814,64 @@ namespace MiscServices { return ErrorCode::NO_ERROR; } + void InputMethodSystemAbility::OnDisplayOptionalInputMethod(int32_t userId) + { + IMSA_HILOGI("InputMethodSystemAbility::OnDisplayOptionalInputMethod"); + std::vector properties; + listInputMethodByUserId(userId, &properties); + if (properties.size() == 0) { + IMSA_HILOGI("InputMethodSystemAbility::OnDisplayOptionalInputMethod has no ime"); + return; + } + std::string defaultIme = ParaHandle::GetDefaultIme(); + std::string params = ""; + std::vector::iterator it; + for (it = properties.begin(); it < properties.end(); ++it) { + if(it == properties.begin()) { + params += "{\"imeList\":["; + }else { + params += "},"; + } + InputMethodProperty *property = (InputMethodProperty*)*it; + std::string imeId = Str16ToStr8(property->mPackageName) + "/" + Str16ToStr8(property->mAbilityName); + params += "{\"ime\": \"" + imeId + "\","; + params += "\"name\": \"" + Str16ToStr8(property->moduleName) + "\","; + params += "\"discription\": \"" + Str16ToStr8(property->description) + "\","; + std::string isDefaultIme = defaultIme == imeId ? "true" : "false"; + params += "\"isDefaultIme\": \"" + isDefaultIme + "\""; + } + params += "}]}"; + + const int TITLE_HEIGHT = 62; + const int SINGLE_IME_HEIGHT = 66; + const int POSTION_X = 0; + const int POSTION_Y = 200; + const int WIDTH = 336; + const int HEIGHT = POSTION_Y + TITLE_HEIGHT + SINGLE_IME_HEIGHT * properties.size(); + Ace::UIServiceMgrClient::GetInstance()->ShowDialog( + "input_method_choose_dialog", + params, + OHOS::Rosen::WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, + POSTION_X, + POSTION_Y, + WIDTH, + HEIGHT, + [this](int32_t id, const std::string& event, const std::string& params) { + IMSA_HILOGI("Dialog callback: %{public}s, %{public}s", event.c_str(), params.c_str()); + if (event == "EVENT_CHANGE_IME") { + std::string defaultIme = ParaHandle::GetDefaultIme(); + if (defaultIme != params) { + StopInputService(defaultIme); + StartInputService(params); + ParaHandle::SetDefaultIme(params); + } + Ace::UIServiceMgrClient::GetInstance()->CancelDialog(id); + } else if (event == "EVENT_START_IME_SETTING") { + Ace::UIServiceMgrClient::GetInstance()->CancelDialog(id); + } + }); + } + /*! Disable input method service. Called from PerUserSession module \n Run in work thread of input method management service \param msg the parameters are saved in msg->msgContent_ @@ -832,5 +927,31 @@ namespace MiscServices { IMSA_HILOGI("End...\n"); return ErrorCode::NO_ERROR; } + + sptr InputMethodSystemAbility::GetBundleMgr() + { + IMSA_HILOGI("InputMethodSystemAbility::GetBundleMgr"); + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + IMSA_HILOGI("InputMethodSystemAbility::GetBundleMgr systemAbilityManager is nullptr"); + return nullptr; + } + sptr remoteObject = + systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + return iface_cast(remoteObject); + } + + sptr InputMethodSystemAbility::GetAbilityManagerService() + { + IMSA_HILOGE("InputMethodSystemAbility::GetAbilityManagerService start"); + sptr abilityMsObj = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (abilityMsObj == nullptr) { + IMSA_HILOGE("failed to get ability manager service"); + return nullptr; + } + return iface_cast(abilityMsObj); + } } } \ No newline at end of file diff --git a/services/src/input_method_system_ability_stub.cpp b/services/src/input_method_system_ability_stub.cpp index 51e1a8c..ecb3afe 100644 --- a/services/src/input_method_system_ability_stub.cpp +++ b/services/src/input_method_system_ability_stub.cpp @@ -124,8 +124,10 @@ namespace MiscServices { break; } case LIST_INPUT_METHOD: { + int32_t uid = IPCSkeleton::GetCallingUid(); + int32_t userId = getUserId(uid); std::vector properties; - int32_t ret = listInputMethod(&properties); + int32_t ret = listInputMethodByUserId(userId, &properties); if (ret != ErrorCode::NO_ERROR) { reply.WriteInt32(ErrorCode::ERROR_EX_ILLEGAL_STATE); // write exception code reply.WriteInt32(-1); @@ -158,6 +160,11 @@ namespace MiscServices { kbdTypes.clear(); break; } + case DISPLAY_OPTIONAL_INPUT_METHOD: { + displayOptionalInputMethod(data); + reply.WriteInt32(NO_ERROR); + break; + } default: { return BRemoteObject::OnRemoteRequest(code, data, reply, option); } @@ -190,6 +197,21 @@ namespace MiscServices { MessageHandler::Instance()->SendMessage(msg); } + void InputMethodSystemAbilityStub::displayOptionalInputMethod(MessageParcel& data) + { + IMSA_HILOGI("InputMethodSystemAbilityStub::displayOptionalInputMethod"); + int32_t pid = IPCSkeleton::GetCallingPid(); + int32_t uid = IPCSkeleton::GetCallingUid(); + int32_t userId = getUserId(uid); + MessageParcel *parcel = new MessageParcel(); + parcel->WriteInt32(userId); + parcel->WriteInt32(pid); + parcel->WriteInt32(uid); + + Message *msg = new Message(MSG_ID_DISPLAY_OPTIONAL_INPUT_METHOD, parcel); + MessageHandler::Instance()->SendMessage(msg); + } + /*! Release input \n Send releaseInput command to work thread. The handling of releaseInput is in the work thread of PerUserSession.