diff --git a/common/BUILD.gn b/common/BUILD.gn index 1f8f84eb320741165eef6ad107e9be3950e39c42..fb12784b175878a9f1694e1fed1c92401ff1d5e7 100644 --- a/common/BUILD.gn +++ b/common/BUILD.gn @@ -45,8 +45,6 @@ ohos_shared_library("inputmethod_common") { "src/inputmethod_sysevent.cpp", "src/inputmethod_trace.cpp", "src/itypes_util.cpp", - "src/message.cpp", - "src/message_handler.cpp", "src/on_demand_start_stop_sa.cpp", "src/string_utils.cpp", ] diff --git a/common/include/global.h b/common/include/global.h index e7d955b5f3ef700ba7a3ef7301af2fd0e52759d2..06411e6daca10a2901a29724f8ed902bb2e58284 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -80,6 +80,7 @@ enum { ERROR_JS_CB_NOT_REGISTER, // only for hiSysEvent ERROR_DEAL_TIMEOUT, // only for hiSysEvent ERROR_IPC_REMOTE_NULLPTR, + ERROR_INVALID_VARIANT_TYPE, ERROR_IMA_BEGIN, ERROR_IME, @@ -98,6 +99,8 @@ enum { ERROR_INVALID_RANGE, ERROR_CLIENT_NOT_BOUND, ERROR_IMC_NULLPTR, + ERROR_IMC_SERVICE_RESPONSE_TIMEOUT, + ERROR_REQUEST_INTERRUPTED, ERROR_IMC_END, ERROR_IMSA_BEGIN, @@ -131,6 +134,12 @@ enum { ERROR_IME_NOT_FOUND, ERROR_OPERATE_SYSTEM_IME, ERROR_SWITCH_IME, + + ERROR_IMSA_REQUESTER_NOT_FOUND, + ERROR_IMSA_TASK_TIMEOUT, + ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED, + ERROR_IMSA_REQUEST_COUNT_OVER_MAXIMUM, + ERROR_SA_POST_TASK_FAILED, ERROR_IMSA_END, }; }; // namespace ErrorCode @@ -159,6 +168,14 @@ static constexpr HiviewDFX::HiLogLabel g_SMALL_SERVICES_LABEL = { LOG_CORE, 0xD0 __FUNCTION__, ##__VA_ARGS__) using Function = std::function; bool BlockRetry(uint32_t interval, uint32_t maxRetryTimes, Function func); + +#define CHECK_NULLPTR_RETURN(pointer, retVal) \ + do { \ + if (pointer == nullptr) { \ + IMSA_HILOGE("" #pointer " is nullptr!"); \ + return retVal; \ + } \ + } while (0) } // namespace MiscServices } // namespace OHOS #endif // SERVICES_INCLUDE_GLOBAL_H diff --git a/common/include/inputmethod_message_handler.h b/common/include/inputmethod_message_handler.h deleted file mode 100644 index f462bbeafa467c9a762de84de2fd4beccd0e21da..0000000000000000000000000000000000000000 --- a/common/include/inputmethod_message_handler.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2021-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 INPUTMETHOD_MESSAGE_HANDLER_H -#define INPUTMETHOD_MESSAGE_HANDLER_H - -#include -#include -#include - -#include "global.h" -#include "message.h" -#include "message_parcel.h" - -namespace OHOS { -namespace MiscServices { -namespace MessageID { -enum { - MSG_ID_USER_START = 0, // a user started - MSG_ID_USER_REMOVED, // a user removed - MSG_ID_PACKAGE_REMOVED, // a package is removed - MSG_ID_BUNDLE_SCAN_FINISHED, // bundle scan finished - MSG_ID_DATA_SHARE_READY, // datashare ready, ready to create data share helper - MSG_ID_PACKAGE_ADDED, - MSG_ID_PACKAGE_CHANGED, - MSG_ID_SYS_LANGUAGE_CHANGED, - MSG_ID_OS_ACCOUNT_STARTED, - MSG_ID_BOOT_COMPLETED, - MSG_ID_SCREEN_UNLOCK, - MSG_ID_SELECT_BY_RANGE, - MSG_ID_SELECT_BY_MOVEMENT, - MSG_ID_HANDLE_EXTEND_ACTION, - MSG_ID_USER_STOP, - MSG_ID_REGULAR_UPDATE_IME_INFO, - - MSG_ID_HIDE_KEYBOARD_SELF, // hide the current keyboard - - // the request from IMSA to IMC - MSG_ID_INSERT_CHAR, - MSG_ID_DELETE_FORWARD, - MSG_ID_DELETE_BACKWARD, - MSG_ID_ON_INPUT_STOP, - MSG_ID_SEND_KEYBOARD_STATUS, - MSG_ID_SEND_FUNCTION_KEY, - MSG_ID_MOVE_CURSOR, - MSG_ID_ON_SWITCH_INPUT, - MSG_ID_GET_TEXT_INDEX_AT_CURSOR, - MSG_ID_GET_TEXT_BEFORE_CURSOR, - MSG_ID_GET_TEXT_AFTER_CURSOR, - MSG_ID_ON_PANEL_STATUS_CHANGE, - - // the request from IMSA to IMA - MSG_ID_INIT_INPUT_CONTROL_CHANNEL, - MSG_ID_SET_SUBTYPE, - - // the request from IMC to IMA - MSG_ID_ON_CURSOR_UPDATE, - MSG_ID_ON_SELECTION_CHANGE, - MSG_ID_ON_CONFIGURATION_CHANGE, - MSG_ID_ON_ATTRIBUTE_CHANGE, - MSG_ID_QUIT_WORKER_THREAD, - MSG_ID_SET_COREANDANGENT, -}; -} - -class MessageHandler { -public: - MessageHandler(); - ~MessageHandler(); - void SendMessage(Message *msg); - Message *GetMessage(); - static MessageHandler *Instance(); - static std::mutex handlerMutex_; - -private: - std::mutex mMutex; // a mutex to guard message queue - std::condition_variable mCV; // condition variable to work with mMutex - std::queue mQueue; // Message queue, guarded by mMutex; - - MessageHandler(const MessageHandler &); - MessageHandler &operator=(const MessageHandler &); - MessageHandler(const MessageHandler &&); - MessageHandler &operator=(const MessageHandler &&); -}; -} // namespace MiscServices -} // namespace OHOS -#endif // INPUTMETHOD_MESSAGE_HANDLER_H diff --git a/common/include/variant_util.h b/common/include/variant_util.h index 347ba8da8e10edb8bb84add3ef6745411b54d321..c00001e1f2c8a20af8997708c494ca5623cd8ca2 100644 --- a/common/include/variant_util.h +++ b/common/include/variant_util.h @@ -25,19 +25,8 @@ namespace OHOS { namespace MiscServices { class VariantUtil { public: - template - static bool GetValue( - const std::variant &input, T &output) - { - if (!std::holds_alternative(input)) { - return false; - } - output = std::get(input); - return true; - } - - template - static bool GetValue(const ResponseData &input, T &output) + template + static bool GetValue(const std::variant &input, T &output) { if (!std::holds_alternative(input)) { return false; @@ -46,6 +35,20 @@ public: return true; } }; + +#define GET_VARIANT_DATA_VALUE(input, output, retVal) \ + do { \ + if (!VariantUtil::GetValue(input, output)) { \ + return ErrorCode::ERROR_IMSA_NULLPTR; \ + } \ + } while (0) + +#define GET_VARIANT_DATA_VALUE_RETURN_VOID(input, output) \ + do { \ + if (!VariantUtil::GetValue(input, output)) { \ + return; \ + } \ + } while (0) } // namespace MiscServices } // namespace OHOS #endif // OHOS_VARIANT_UTIL_H diff --git a/common/src/message.cpp b/common/src/message.cpp deleted file mode 100644 index 45034cd399ecaac9287c42c053fcc0b8db133672..0000000000000000000000000000000000000000 --- a/common/src/message.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 "message.h" - -#include "global.h" - -namespace OHOS { -namespace MiscServices { -/*! Constructor - * @param msgId a message Id - * @param msgContent the content of a message - */ -Message::Message(int32_t msgId, MessageParcel *msgContent) -{ - msgId_ = msgId; - msgContent_ = msgContent; - if (msgContent_ != nullptr) { - msgContent_->RewindRead(0); - } -} - -/*!Constructor - * @param msg a source message - */ -Message::Message(const Message &msg) -{ - msgId_ = msg.msgId_; - if (msgContent_ != nullptr) { - delete msgContent_; - msgContent_ = nullptr; - } - MessageParcel *src = msg.msgContent_; - if (src != nullptr) { - msgContent_ = new (std::nothrow) MessageParcel(); - if (msgContent_ == nullptr) { - IMSA_HILOGE("new MessageParcel failed"); - return; - } - msgContent_->ParseFrom(src->GetData(), src->GetDataSize()); - } -} - -Message &Message::operator=(const Message &msg) -{ - if (this == &msg) { - return *this; - } - msgId_ = msg.msgId_; - if (msgContent_ != nullptr) { - delete msgContent_; - msgContent_ = nullptr; - } - if (msg.msgContent_ != nullptr) { - msgContent_ = new (std::nothrow) MessageParcel(); - if (msgContent_ == nullptr) { - IMSA_HILOGE("new MessageParcel failed"); - return *this; - } - msgContent_->ParseFrom(msg.msgContent_->GetData(), msg.msgContent_->GetDataSize()); - msgContent_->RewindRead(0); - } - return *this; -} - -Message::~Message() -{ - if (msgContent_ != nullptr) { - delete msgContent_; - msgContent_ = nullptr; - } -} -} // namespace MiscServices -} // namespace OHOS diff --git a/frameworks/native/common/include/response_data_util.h b/frameworks/native/common/include/response_data_util.h new file mode 100644 index 0000000000000000000000000000000000000000..f0fe0e094961e899b0161d7d433d1b9304987acb --- /dev/null +++ b/frameworks/native/common/include/response_data_util.h @@ -0,0 +1,69 @@ +/* + * 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 IMF_FRAMEWORKS_RESPONSE_DATA_UTIL_H +#define IMF_FRAMEWORKS_RESPONSE_DATA_UTIL_H + +#include +#include + +#include "input_method_property.h" +#include "input_method_utils.h" + +namespace OHOS { +namespace MiscServices { +const int VECTOR_MAX_SIZE = 102400; +class ResponseDataUtil { +public: + template static bool Unmarshall(Parcel &in, std::vector &out) + { + int32_t size = 0; + if (!in.ReadInt32(size)) { + return false; + } + if (size > static_cast(VECTOR_MAX_SIZE)) { + return false; + } + for (int32_t i = 0; i < size; ++i) { + std::unique_ptr value(in.ReadParcelable()); + if (value == nullptr) { + return false; + } + out.push_back(*value); + } + return true; + } + + template static bool Marshall(const std::vector &in, Parcel &out) + { + auto size = in.size(); + if (size > static_cast(VECTOR_MAX_SIZE)) { + return false; + } + if (!out.WriteInt32(size)) { + return false; + } + for (const auto &it : in) { + if (!it.Marshalling(out)) { + return false; + } + } + return true; + } +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_FRAMEWORKS_RESPONSE_DATA_UTIL_H diff --git a/frameworks/native/common/include/service_response_data.h b/frameworks/native/common/include/service_response_data.h new file mode 100644 index 0000000000000000000000000000000000000000..59ca757477bb48d2d0861781db19e68c523973ca --- /dev/null +++ b/frameworks/native/common/include/service_response_data.h @@ -0,0 +1,173 @@ +/* + * 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 IMF_FRAMEWORKS_SERVICE_RESPONSE_DATA_H +#define IMF_FRAMEWORKS_SERVICE_RESPONSE_DATA_H + +#include +#include +#include +#include + +#include "element_name.h" +#include "input_method_property.h" +#include "input_method_utils.h" +#include "response_data_util.h" + +namespace OHOS { +namespace MiscServices { +using RequestId = uint32_t; +using RequestFunc = std::function; + +struct StartInputResponse : public Parcelable { + sptr agent{ nullptr }; + int64_t pid{ 0 }; + std::string bundleName; + void Set(sptr imeAgent, int64_t imePid, const std::string &imeBundleName); + bool ReadFromParcel(Parcel &in); + bool Marshalling(Parcel &out) const override; + static StartInputResponse *Unmarshalling(Parcel &in); +}; + +struct InputStartInfo : public Parcelable { + bool isInputStart{ false }; + uint32_t callingWindowId{ 0 }; + int32_t requestKeyboardReason{ 0 }; + void Set(bool inputStart, uint32_t id, int32_t reason); + bool ReadFromParcel(Parcel &in); + bool Marshalling(Parcel &out) const override; + static InputStartInfo *Unmarshalling(Parcel &in); +}; + +enum ServiceDataType : int32_t { + TYPE_MONOSTATE = 0, + + // basic types + TYPE_BOOL = 1, + TYPE_INT32, + TYPE_UINT32, + TYPE_INT64, + TYPE_UINT64, + TYPE_REMOTE_OBJECT, + + // inner types + TYPE_PROPERTY, + TYPE_PROPERTIES, + TYPE_SUB_PROPERTY, + TYPE_SUB_PROPERTIES, + TYPE_START_INPUT_RESPONSE, + TYPE_INPUT_START_INFO, + + // external types + TYPE_AMS_ELEMENT_NAME, + + TYPE_END, +}; + +using ServiceResponseData = std::variant, Property, std::vector, SubProperty, std::vector, StartInputResponse, + InputStartInfo, AppExecFwk::ElementName>; + +struct ServiceResponse { + int32_t result{ 0 }; + ServiceResponseData responseData{ std::monostate{} }; +}; + +struct PendingRequest { + std::promise promise; +}; + +using UnmarshalFunc = std::function; +struct ServiceResponseDataInner : public Parcelable { +public: + bool ReadFromParcel(Parcel &in); + bool Marshalling(Parcel &out) const override; + static ServiceResponseDataInner *Unmarshalling(Parcel &in); + ServiceResponseData data; + +private: + static const std::unordered_map UNMARSHAL_FUNCTION_MAP; +}; + +struct ServiceResponseWriter { + Parcel &out; + bool result = true; + + explicit ServiceResponseWriter(Parcel &parcel) : out(parcel) + { + } + + void operator()(std::monostate val) + { + IMSA_HILOGD("no need to marshal"); + result = true; + } + void operator()(bool val) + { + result = out.WriteBool(val); + } + void operator()(int32_t val) + { + result = out.WriteInt32(val); + } + void operator()(uint32_t val) + { + result = out.WriteUint32(val); + } + void operator()(int64_t val) + { + result = out.WriteInt64(val); + } + void operator()(uint64_t val) + { + result = out.WriteUint64(val); + } + void operator()(sptr val) + { + result = static_cast(&out)->WriteRemoteObject(val); + } + void operator()(const Property &val) + { + result = val.Marshalling(out); + } + void operator()(const std::vector &val) + { + result = ResponseDataUtil::Marshall(val, out); + } + void operator()(const SubProperty &val) + { + result = val.Marshalling(out); + } + void operator()(const std::vector &val) + { + result = ResponseDataUtil::Marshall(val, out); + } + void operator()(const StartInputResponse &val) + { + result = val.Marshalling(out); + } + void operator()(const InputStartInfo &val) + { + result = val.Marshalling(out); + } + void operator()(const AppExecFwk::ElementName &val) + { + result = val.Marshalling(out); + } +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_FRAMEWORKS_SERVICE_RESPONSE_DATA_H diff --git a/frameworks/native/common/src/service_response_data.cpp b/frameworks/native/common/src/service_response_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e86dfe3f1c977d61a9f3f1f48692251046c9c5f --- /dev/null +++ b/frameworks/native/common/src/service_response_data.cpp @@ -0,0 +1,226 @@ +/* + * 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 "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +const std::unordered_map ServiceResponseDataInner::UNMARSHAL_FUNCTION_MAP = { + { static_cast(TYPE_MONOSTATE), [](Parcel &in, ServiceResponseData &out) { out = std::monostate{}; } }, + { static_cast(TYPE_BOOL), [](Parcel &in, ServiceResponseData &out) { out = in.ReadBool(); } }, + { static_cast(TYPE_INT32), [](Parcel &in, ServiceResponseData &out) { out = in.ReadInt32(); } }, + { static_cast(TYPE_UINT32), [](Parcel &in, ServiceResponseData &out) { out = in.ReadUint32(); } }, + { static_cast(TYPE_INT64), [](Parcel &in, ServiceResponseData &out) { out = in.ReadInt64(); } }, + { static_cast(TYPE_UINT64), [](Parcel &in, ServiceResponseData &out) { out = in.ReadUint64(); } }, + { static_cast(TYPE_REMOTE_OBJECT), + [](Parcel &in, ServiceResponseData &out) { out = static_cast(&in)->ReadRemoteObject(); } }, + { static_cast(TYPE_PROPERTY), + [](Parcel &in, ServiceResponseData &out) { + Property value; + value.ReadFromParcel(in); + out = value; + } }, + { static_cast(TYPE_PROPERTIES), + [](Parcel &in, ServiceResponseData &out) { + std::vector value; + ResponseDataUtil::Unmarshall(in, value); + out = props; + } }, + { static_cast(TYPE_SUB_PROPERTY), + [](Parcel &in, ServiceResponseData &out) { + SubProperty value; + value.ReadFromParcel(in); + out = value; + } }, + { static_cast(TYPE_SUB_PROPERTIES), + [](Parcel &in, ServiceResponseData &out) { + std::vector value; + ResponseDataUtil::Unmarshall(in, value); + out = value; + } }, + { static_cast(TYPE_START_INPUT_RESPONSE), + [](Parcel &in, ServiceResponseData &out) { + StartInputResponse value; + value.ReadFromParcel(in); + out = value; + } }, + { static_cast(TYPE_INPUT_START_INFO), + [](Parcel &in, ServiceResponseData &out) { + InputStartInfo value; + value.ReadFromParcel(in); + out = value; + } }, + { static_cast(TYPE_AMS_ELEMENT_NAME), + [](Parcel &in, ServiceResponseData &out) { + AppExecFwk::ElementName value; + value.ReadFromParcel(in); + out = value; + } }, +}; +bool ServiceResponseDataInner::ReadFromParcel(Parcel &in) +{ + int32_t valueType = 0; + if (!in.ReadInt32(valueType)) { + return false; + } + if (valueType < static_cast(ServiceDataType::TYPE_MONOSTATE) + || valueType >= static_cast(ServiceDataType::TYPE_END)) { + IMSA_HILOGE("invalid value type"); + return false; + } + auto iter = UNMARSHAL_FUNCTION_MAP.find(valueType); + if (iter == UNMARSHAL_FUNCTION_MAP.end()) { + return false; + } + auto handler = iter->second; + if (handler == nullptr) { + return false; + } + handler(in, data); + return true; +} + +bool ServiceResponseDataInner::Marshalling(Parcel &out) const +{ + int32_t valueType = static_cast(data.index()); + if (valueType < static_cast(ServiceDataType::TYPE_MONOSTATE) + || valueType >= static_cast(ServiceDataType::TYPE_END)) { + IMSA_HILOGE("valid value type"); + return false; + } + if (!out.WriteInt32(valueType)) { + IMSA_HILOGE("failed to write valueType"); + return false; + } + if (valueType == static_cast(ServiceDataType::TYPE_MONOSTATE)) { + return true; + } + ServiceResponseWriter writer{ out }; + std::visit(writer, data); + if (!writer.result) { + IMSA_HILOGE("failed to write response data"); + return false; + } + return true; +} + +ServiceResponseDataInner *ServiceResponseDataInner::Unmarshalling(Parcel &in) +{ + auto data = new (std::nothrow) ServiceResponseDataInner(); + if (data && !data->ReadFromParcel(in)) { + delete data; + data = nullptr; + } + return data; +} + +void StartInputResponse::Set(sptr imeAgent, int64_t imePid, const std::string &imeBundleName) +{ + agent = imeAgent; + pid = imePid; + bundleName = imeBundleName; +} + +bool StartInputResponse::ReadFromParcel(Parcel &in) +{ + agent = static_cast(&in)->ReadRemoteObject(); + if (agent == nullptr) { + return false; + } + if (!in.ReadInt64(pid)) { + return false; + } + if (!in.ReadString(bundleName)) { + return false; + } + return true; +} + +bool StartInputResponse::Marshalling(Parcel &out) const +{ + if (!static_cast(&out)->WriteRemoteObject(agent)) { + return false; + } + if (!out.WriteInt64(pid)) { + return false; + } + if (!out.WriteString(bundleName)) { + return false; + } + return true; +} + +StartInputResponse *StartInputResponse::Unmarshalling(Parcel &in) +{ + auto data = new (std::nothrow) StartInputResponse(); + if (data == nullptr) { + return nullptr; + } + if (!data->ReadFromParcel(in)) { + delete data; + return nullptr; + } + return data; +} + +void InputStartInfo::Set(bool inputStart, uint32_t id, int32_t reason) +{ + isInputStart = inputStart; + callingWindowId = id; + requestKeyboardReason = reason; +} + +bool InputStartInfo::ReadFromParcel(Parcel &in) +{ + if (!in.ReadBool(isInputStart)) { + return false; + } + if (!in.ReadUint32(callingWindowId)) { + return false; + } + if (!in.ReadInt32(requestKeyboardReason)) { + return false; + } + return true; +} + +bool InputStartInfo::Marshalling(Parcel &out) const +{ + if (!out.WriteBool(isInputStart)) { + return false; + } + if (!out.WriteUint32(callingWindowId)) { + return false; + } + if (!out.WriteInt32(requestKeyboardReason)) { + return false; + } + return true; +} + +InputStartInfo *InputStartInfo::Unmarshalling(Parcel &in) +{ + auto data = new (std::nothrow) InputStartInfo(); + if (data == nullptr) { + return nullptr; + } + if (!data->ReadFromParcel(in)) { + delete data; + return nullptr; + } + return data; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/IImaResponseChannel.idl b/frameworks/native/inputmethod_ability/IImaResponseChannel.idl new file mode 100644 index 0000000000000000000000000000000000000000..475fcd212a9606b735dc431d0e0905088fbf6ccd --- /dev/null +++ b/frameworks/native/inputmethod_ability/IImaResponseChannel.idl @@ -0,0 +1,20 @@ +/* + * 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. + */ + +sequenceable service_response_data..OHOS.MiscServices.ServiceResponseDataInner; +interface OHOS.MiscServices.IImaResponseChannel { + [oneway] void OnResponse( + [in] unsigned int requestId, [in] int resultErrCode, [in] ServiceResponseDataInner response); +} diff --git a/frameworks/native/inputmethod_ability/include/ima_response_channel_impl.h b/frameworks/native/inputmethod_ability/include/ima_response_channel_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..5bc82c1e8f85bacb5d846226e62046ea766dedc1 --- /dev/null +++ b/frameworks/native/inputmethod_ability/include/ima_response_channel_impl.h @@ -0,0 +1,38 @@ +/* + * 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 IMF_IMA_RESPONSE_CHANNEL_IMPL_H +#define IMF_IMA_RESPONSE_CHANNEL_IMPL_H + +#include "iima_response_channel.h" +#include "ima_response_channel_stub.h" +#include "iremote_object.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +class ImaResponseChannelImpl final + : public ImaResponseChannelStub + , public std::enable_shared_from_this { + DISALLOW_COPY_AND_MOVE(ImaResponseChannelImpl); + +public: + ImaResponseChannelImpl(); + ~ImaResponseChannelImpl(); + ErrCode OnResponse(uint32_t requestId, int32_t resultErrCode, const ServiceResponseDataInner &response) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // IMF_IMA_RESPONSE_CHANNEL_IMPL_H diff --git a/frameworks/native/inputmethod_ability/include/ima_service_proxy.h b/frameworks/native/inputmethod_ability/include/ima_service_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..561d126944768ba4d5be641d1cbf9d488d506c4c --- /dev/null +++ b/frameworks/native/inputmethod_ability/include/ima_service_proxy.h @@ -0,0 +1,96 @@ +/* + * 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 IMF_IMA_SERVICE_PROXY_H +#define IMF_IMA_SERVICE_PROXY_H + +#include +#include +#include +#include + +#include "iima_response_channel.h" +#include "iinput_method_system_ability.h" +#include "input_death_recipient.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +class ImaServiceProxy { +private: + ImaServiceProxy(); + +public: + static ImaServiceProxy &GetInstance(); + + ~ImaServiceProxy() = default; + ImaServiceProxy(const ImaServiceProxy &) = delete; + ImaServiceProxy(ImaServiceProxy &&) = delete; + ImaServiceProxy &operator=(const ImaServiceProxy &) = delete; + ImaServiceProxy &operator=(ImaServiceProxy &&) = delete; + + int32_t SendRequest(const RequestFunc &request, int64_t timeout); + template + int32_t SendRequest(const RequestFunc &request, ResultType &resultValue, int64_t timeout); + + void OnResponse(RequestId id, const ServiceResponse &responseData); + + void RemoveDeathRecipient(); + +public: + int32_t SetCoreAndAgent(const sptr &core, const sptr &agent); + int32_t InitConnect(); + int32_t RegisterProxyIme(uint64_t displayId, const sptr &core, const sptr &agent); + int32_t UnregisterProxyIme(uint64_t displayId); + int32_t UnRegisteredProxyIme(int32_t type, sptr core); + int32_t ExitCurrentInputType(); + int32_t PanelStatusChange(uint32_t status, const ImeWindowInfo &info); + int32_t GetSecurityMode(int32_t &security); + int32_t IsDefaultImeScreen(uint64_t displayId, bool &resultValue); + int32_t IsCapacitySupport(int32_t capacity, bool &isSupport); + int32_t IsCurrentIme(bool &resultValue); + int32_t IsDefaultIme(bool &resultValue); + int32_t IsSystemImeApp(bool &resultValue); + +private: + void Init(); + RequestId GetNextRequestId(); + int32_t RegisterResponseChannel(); + int32_t SendRequestInner(const RequestFunc &request, ServiceResponseData &responseData, int64_t timeout); + + void OnRemoteSaDied(const wptr &remote); + sptr GetSystemAbilityProxy(bool ifRetry = true); + + void AddRequest(RequestId id, PendingRequest pendingRequest); + void RemoveRequest(RequestId requestId); + + std::atomic hasRegistered_{ false }; + std::mutex abilityLock_{}; + sptr abilityManager_ = nullptr; + sptr deathRecipient_; + + std::atomic currentRequestId_{ 0 }; + std::atomic isInterrupted_{ false }; + + std::mutex requestsMutex_{}; + std::unordered_map pendingRequests_; + std::atomic lastId_{ 0 }; + + sptr responseChannelStub_{ nullptr }; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_IMA_SERVICE_PROXY_H diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index e0bc426d10628b42856dfd6bdd57bcaf76d448f5..a1d01f1577b3ea058913b3137d0c059f2c009828 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -25,23 +25,21 @@ #include "iinput_data_channel.h" #include "iinput_method_agent.h" #include "iinput_method_core.h" -#include "iinput_method_system_ability.h" #include "input_attribute.h" #include "input_control_channel_proxy.h" #include "input_data_channel_proxy.h" +#include "input_data_channel_proxy_wrap.h" #include "input_method_engine_listener.h" #include "input_method_panel.h" #include "input_method_types.h" #include "input_method_utils.h" #include "iremote_object.h" -#include "keyboard_listener.h" #include "key_event_consumer_proxy.h" -#include "text_input_client_listener.h" +#include "keyboard_listener.h" #include "msg_handler_callback_interface.h" #include "private_command_interface.h" #include "system_cmd_channel_proxy.h" -#include "inputmethod_message_handler.h" -#include "input_data_channel_proxy_wrap.h" +#include "text_input_client_listener.h" namespace OHOS { namespace MiscServices { @@ -127,6 +125,9 @@ public: void OnAttributeChange(InputAttribute attribute); int32_t OnStopInputService(bool isTerminateIme); + + void OnRemoteSaDied(const wptr &object); + private: std::mutex controlChannelLock_; std::shared_ptr controlChannel_ = nullptr; @@ -142,15 +143,10 @@ private: std::shared_ptr kdListener_; std::shared_ptr textInputClientListener_; - std::mutex abilityLock_; - sptr abilityManager_ { nullptr }; - sptr deathRecipient_ { nullptr }; InputMethodAbility(); ~InputMethodAbility(); InputMethodAbility(const InputMethodAbility &) = delete; InputMethodAbility &operator=(const InputMethodAbility &) = delete; - sptr GetImsaProxy(); - void OnRemoteSaDied(const wptr &object); sptr GetSystemCmdChannelProxy(); void ClearSystemCmdChannel(); diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h b/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h index dda07ef7a592d3582bd75ba32ffd801c35e55891..78141516f17d51a376092084c06d385ae8d7923d 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h @@ -21,7 +21,6 @@ #include "iinput_method_core.h" #include "input_method_core_stub.h" #include "iremote_object.h" -#include "inputmethod_message_handler.h" namespace OHOS { namespace MiscServices { diff --git a/common/include/message.h b/frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp similarity index 50% rename from common/include/message.h rename to frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp index 9962415e91d732fe28507a3892b283fdb4201aaa..87ac7e439a1e6f57a73212b26cac03df851bca26 100644 --- a/common/include/message.h +++ b/frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -13,30 +13,27 @@ * limitations under the License. */ -/*! \file MessageHandler.h */ -#ifndef SERVICES_INCLUDE_MESSAGE_H -#define SERVICES_INCLUDE_MESSAGE_H +#include "ima_response_channel_impl.h" -#include - -#include "message_parcel.h" +#include "ima_service_proxy.h" namespace OHOS { namespace MiscServices { -class Message { -public: - int32_t msgId_{ 0 }; // message id - MessageParcel *msgContent_ = nullptr; // message content - Message(int32_t msgId, MessageParcel *msgContent); - explicit Message(const Message &msg); - Message &operator=(const Message &msg); - ~Message(); -private: - Message(const Message &&); - Message &operator=(const Message &&); -}; -} // namespace MiscServices -} // namespace OHOS +ImaResponseChannelImpl::ImaResponseChannelImpl() +{ +} -#endif // SERVICES_INCLUDE_MESSAGE_H +ImaResponseChannelImpl::~ImaResponseChannelImpl() +{ +} + +ErrCode ImaResponseChannelImpl::OnResponse( + uint32_t requestId, int32_t resultErrCode, const ServiceResponseDataInner &response) +{ + ServiceResponse serviceResponse = { .result = resultErrCode, .responseData = response.data }; + ImaServiceProxy::GetInstance().OnResponse(requestId, serviceResponse); + return ERR_OK; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp b/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32ee1ea0253501de54c99a51af4ff777675376cf --- /dev/null +++ b/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp @@ -0,0 +1,445 @@ +/* + * 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 "ima_service_proxy.h" + +#include "ima_response_channel_impl.h" +#include "input_method_ability.h" +#include "on_demand_start_stop_sa.h" +#include "variant_util.h" + +namespace OHOS { +namespace MiscServices { +constexpr int64_t COMPLEX_REQUEST_TIMEOUT = 2000; +constexpr int64_t NORMAL_TIMEOUT = 1000; +constexpr int64_t QUERY_TIMEOUT = 100; +#define CHECK_RESPONSE_CHANNEL(retVal) \ + do { \ + auto ret = RegisterResponseChannel(); \ + if (ret != ErrorCode::NO_ERROR) { \ + IMSA_HILOGD("failed to register to sa, ret: %{public}d", ret); \ + return retVal; \ + } \ + } while (0) + +ImaServiceProxy &ImaServiceProxy::GetInstance() +{ + static ImaServiceProxy ImaServiceProxy; + return ImaServiceProxy; +} + +ImaServiceProxy::ImaServiceProxy() +{ + Init(); +} + +void ImaServiceProxy::Init() +{ + IMSA_HILOGD("start"); + sptr channel = new (std::nothrow) ImaResponseChannelImpl(); + if (channel == nullptr) { + IMSA_HILOGE("failed to create channel!"); + return; + } + responseChannelStub_ = channel; +} + +RequestId ImaServiceProxy::GetNextRequestId() +{ + static std::atomic seqId{ 1 }; + return seqId.fetch_add(1, std::memory_order_seq_cst); +} + +void ImaServiceProxy::OnResponse(RequestId id, const ServiceResponse &responseData) +{ + std::lock_guard lock(requestsMutex_); + auto iter = pendingRequests_.find(id); + if (iter == pendingRequests_.end()) { + IMSA_HILOGE("failed to find pending request, id: %{public}d", id); + return; + } + IMSA_HILOGD("id: %{public}d", id); + iter->second.promise.set_value(responseData); +} + +sptr ImaServiceProxy::GetSystemAbilityProxy(bool ifRetry) +{ + std::lock_guard lock(abilityLock_); + if (abilityManager_ != nullptr) { + return abilityManager_; + } + IMSA_HILOGD("get input method service proxy."); + auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(ifRetry); + if (systemAbility == nullptr) { + IMSA_HILOGE("systemAbility is nullptr!"); + return nullptr; + } + + if (deathRecipient_ == nullptr) { + deathRecipient_ = new (std::nothrow) InputDeathRecipient(); + if (deathRecipient_ == nullptr) { + IMSA_HILOGE("create death recipient failed!"); + return nullptr; + } + } + deathRecipient_->SetDeathRecipient([this](const wptr &remote) { OnRemoteSaDied(remote); }); + if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { + IMSA_HILOGE("failed to add death recipient!"); + return nullptr; + } + abilityManager_ = iface_cast(systemAbility); + return abilityManager_; +} + +void ImaServiceProxy::RemoveDeathRecipient() +{ + std::lock_guard lock(abilityLock_); + if (abilityManager_ != nullptr && abilityManager_->AsObject() != nullptr && deathRecipient_ != nullptr) { + abilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_); + } + deathRecipient_ = nullptr; + abilityManager_ = nullptr; +} + +int32_t ImaServiceProxy::SendRequest(const RequestFunc &request, int64_t timeout) +{ + if (request == nullptr) { + IMSA_HILOGE("request is nullptr"); + return ErrorCode::ERROR_IMC_NULLPTR; + } + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + PendingRequest pendingRequest; + RequestId id = GetNextRequestId(); + auto future = pendingRequest.promise.get_future(); + AddRequest(id, std::move(pendingRequest)); + + // send request + int32_t ret = request(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("request failed, ret: %{public}d", ret); + RemoveRequest(id); + return ret; + } + + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + // wait till timeout + if (future.wait_for(std::chrono::milliseconds(timeout)) != std::future_status::ready) { + IMSA_HILOGE("service handle timeout"); + RemoveRequest(id); + return ErrorCode::ERROR_IMC_SERVICE_RESPONSE_TIMEOUT; + } + + // handle response + ServiceResponse response = future.get(); + ret = response.result; + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("task failed"); + return ret; + } + return ErrorCode::NO_ERROR; +} + +int32_t ImaServiceProxy::SendRequestInner( + const RequestFunc &request, ServiceResponseData &responseData, int64_t timeout) +{ + if (request == nullptr) { + IMSA_HILOGE("request is nullptr"); + return ErrorCode::ERROR_IMC_NULLPTR; + } + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + + PendingRequest pendingRequest; + RequestId id = GetNextRequestId(); + auto future = pendingRequest.promise.get_future(); + AddRequest(id, std::move(pendingRequest)); + + // send request + int32_t ret = request(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("request failed, ret: %{public}d", ret); + RemoveRequest(id); + return ret; + } + + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + // wait till timeout + if (future.wait_for(std::chrono::milliseconds(timeout)) != std::future_status::ready) { + IMSA_HILOGE("service handle timeout"); + RemoveRequest(id); + return ErrorCode::ERROR_IMC_SERVICE_RESPONSE_TIMEOUT; + } + + // handle response + ServiceResponse response = future.get(); + ret = response.result; + RemoveRequest(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("task failed"); + return ret; + } + responseData = response.responseData; + return ErrorCode::NO_ERROR; +} + +template +int32_t ImaServiceProxy::SendRequest(const RequestFunc &request, ResultType &resultValue, int64_t timeout) +{ + ServiceResponseData responseData; + int32_t ret = SendRequestInner(request, responseData, timeout); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + if (!VariantUtil::GetValue(responseData, resultValue)) { + IMSA_HILOGE("failed to get result value"); + return ErrorCode::ERROR_INVALID_VARIANT_TYPE; + } + return ErrorCode::NO_ERROR; +} + +void ImaServiceProxy::OnRemoteSaDied(const wptr &remote) +{ + hasRegistered_.store(false); + { + std::lock_guard lock(abilityLock_); + abilityManager_ = nullptr; + } + + // notify InputMethodAbility sa died + InputMethodAbility::GetInstance().OnRemoteSaDied(remote); +} + +int32_t ImaServiceProxy::RegisterResponseChannel() +{ + if (hasRegistered_.load()) { + return ErrorCode::NO_ERROR; + } + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get sa proxy"); + return ErrorCode::ERROR_IPC_REMOTE_NULLPTR; + } + return proxy->RegisterImaResponseChannel(responseChannelStub_); +} + +void ImaServiceProxy::AddRequest(RequestId id, PendingRequest pendingRequest) +{ + std::lock_guard lock(requestsMutex_); + pendingRequests_[id] = std::move(pendingRequest); + currentRequestId_.store(id); +} + +void ImaServiceProxy::RemoveRequest(RequestId requestId) +{ + std::lock_guard lock(requestsMutex_); + pendingRequests_.erase(requestId); + currentRequestId_.store(0); +} + +int32_t ImaServiceProxy::SetCoreAndAgent(const sptr &core, const sptr &agent) +{ + RequestFunc requestFunc = [this, core, agent](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->SetCoreAndAgent(requestId, core, agent); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImaServiceProxy::InitConnect() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->InitConnect(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImaServiceProxy::RegisterProxyIme( + uint64_t displayId, const sptr &core, const sptr &agent) +{ + RequestFunc requestFunc = [this, displayId, core, agent](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->RegisterProxyIme(requestId, displayId, core, agent); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImaServiceProxy::UnregisterProxyIme(uint64_t displayId) +{ + RequestFunc requestFunc = [this, displayId](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->UnregisterProxyIme(requestId, displayId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImaServiceProxy::UnRegisteredProxyIme(int32_t type, sptr core) +{ + RequestFunc requestFunc = [this, type, core](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->UnRegisteredProxyIme(requestId, type, core); + }; + return SendRequest(requestFunc, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImaServiceProxy::ExitCurrentInputType() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ExitCurrentInputType(requestId); + }; + return SendRequest(requestFunc, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImaServiceProxy::PanelStatusChange(uint32_t status, const ImeWindowInfo &info) +{ + RequestFunc requestFunc = [this, status, info](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->PanelStatusChange(requestId, status, info); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImaServiceProxy::GetSecurityMode(int32_t &security) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->GetSecurityMode(requestId); + }; + return SendRequest(requestFunc, security, QUERY_TIMEOUT); +} + +int32_t ImaServiceProxy::IsDefaultImeScreen(uint64_t displayId, bool &resultValue) +{ + RequestFunc requestFunc = [this, displayId](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsDefaultImeScreen(requestId, displayId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImaServiceProxy::IsCapacitySupport(int32_t capacity, bool &isSupport) +{ + RequestFunc requestFunc = [this, capacity](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsCapacitySupport(requestId, capacity); + }; + return SendRequest(requestFunc, isSupport, QUERY_TIMEOUT); +} + +int32_t ImaServiceProxy::IsCurrentIme(bool &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsCurrentIme(requestId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImaServiceProxy::IsDefaultIme(bool &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsDefaultIme(requestId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImaServiceProxy::IsSystemImeApp(bool &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsSystemImeApp(requestId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 79f845e78149252f71ab0e5107ce9422dccba8e2..a4dde987c7662e6d5560ac9b1c940ddbd7814ed4 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -16,24 +16,21 @@ #include "input_method_ability.h" #include + #include #include "global.h" #include "ima_hisysevent_reporter.h" +#include "ima_service_proxy.h" #include "input_method_agent_service_impl.h" #include "input_method_core_service_impl.h" -#include "input_method_system_ability_proxy.h" #include "input_method_tools.h" #include "input_method_utils.h" #include "inputmethod_sysevent.h" #include "inputmethod_trace.h" -#include "iservice_registry.h" #include "itypes_util.h" -#include "message_parcel.h" -#include "on_demand_start_stop_sa.h" #include "string_ex.h" #include "sys/prctl.h" -#include "system_ability_definition.h" #include "task_manager.h" #include "tasks/task.h" #include "tasks/task_imsa.h" @@ -41,7 +38,6 @@ namespace OHOS { namespace MiscServices { -using namespace MessageID; using namespace std::chrono; constexpr double INVALID_CURSOR_VALUE = -1.0; constexpr int32_t INVALID_SELECTION_VALUE = -1; @@ -67,36 +63,6 @@ InputMethodAbility &InputMethodAbility::GetInstance() return instance; } -sptr InputMethodAbility::GetImsaProxy() -{ - std::lock_guard lock(abilityLock_); - if (abilityManager_ != nullptr) { - return abilityManager_; - } - IMSA_HILOGI("InputMethodAbility get imsa proxy."); - auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(); - if (systemAbility == nullptr) { - IMSA_HILOGE("systemAbility is nullptr!"); - return nullptr; - } - if (deathRecipient_ == nullptr) { - deathRecipient_ = new (std::nothrow) InputDeathRecipient(); - if (deathRecipient_ == nullptr) { - IMSA_HILOGE("failed to new death recipient!"); - return nullptr; - } - } - deathRecipient_->SetDeathRecipient([this](const wptr &remote) { - OnRemoteSaDied(remote); - }); - if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { - IMSA_HILOGE("failed to add death recipient!"); - return nullptr; - } - abilityManager_ = iface_cast(systemAbility); - return abilityManager_; -} - int32_t InputMethodAbility::SetCoreAndAgent() { IMSA_HILOGD("InputMethodAbility, start."); @@ -106,12 +72,7 @@ int32_t InputMethodAbility::SetCoreAndAgent() IMSA_HILOGD("already bound."); return ErrorCode::NO_ERROR; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - int32_t ret = proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject()); + int32_t ret = ImaServiceProxy::GetInstance().SetCoreAndAgent(coreStub_, agentStub_->AsObject()); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("set failed, ret: %{public}d!", ret); return ret; @@ -124,12 +85,7 @@ int32_t InputMethodAbility::SetCoreAndAgent() int32_t InputMethodAbility::InitConnect() { IMSA_HILOGD("InputMethodAbility, init connect."); - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - int32_t ret = proxy->InitConnect(); + int32_t ret = ImaServiceProxy::GetInstance().InitConnect(); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("set failed, ret: %{public}d!", ret); return ret; @@ -140,12 +96,7 @@ int32_t InputMethodAbility::InitConnect() int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type) { isBound_.store(false); - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - return proxy->UnRegisteredProxyIme(static_cast(type), coreStub_); + return ImaServiceProxy::GetInstance().UnRegisteredProxyIme(static_cast(type), coreStub_); } int32_t InputMethodAbility::RegisterProxyIme(uint64_t displayId) @@ -157,18 +108,13 @@ int32_t InputMethodAbility::RegisterProxyIme(uint64_t displayId) IMSA_HILOGD("already bound."); return ErrorCode::NO_ERROR; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } if (agentStub_ == nullptr) { IMSA_HILOGE("agent nullptr"); return ErrorCode::ERROR_NULL_POINTER; } int32_t ret = displayId == DEFAULT_DISPLAY_ID ? - proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject()) : - proxy->RegisterProxyIme(displayId, coreStub_, agentStub_->AsObject()); + ImaServiceProxy::GetInstance().SetCoreAndAgent(coreStub_, agentStub_->AsObject()) : + ImaServiceProxy::GetInstance().RegisterProxyIme(displayId, coreStub_, agentStub_->AsObject()); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed, displayId: %{public}" PRIu64 ", ret: %{public}d!", displayId, ret); return ret; @@ -183,12 +129,7 @@ int32_t InputMethodAbility::UnregisterProxyIme(uint64_t displayId) { isBound_.store(false); isProxyIme_.store(false); - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } - return proxy->UnregisterProxyIme(displayId); + return ImaServiceProxy::GetInstance().UnregisterProxyIme(displayId); } void InputMethodAbility::Initialize() @@ -298,19 +239,14 @@ bool InputMethodAbility::IsDisplayChanged(uint64_t oldDisplayId, uint64_t newDis IMSA_HILOGD("screen not changed!"); return false; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("imsa proxy is nullptr!"); - return false; - } bool ret = false; - int32_t result = proxy->IsDefaultImeScreen(oldDisplayId, ret); + int32_t result = ImaServiceProxy::GetInstance().IsDefaultImeScreen(oldDisplayId, ret); if (result != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get oldDisplay info , result is %{public}d!", result); return false; } if (!ret) { - result = proxy->IsDefaultImeScreen(newDisplayId, ret); + result = ImaServiceProxy::GetInstance().IsDefaultImeScreen(newDisplayId, ret); if (result != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get newDisplay info , result is %{public}d!", result); return false; @@ -918,10 +854,6 @@ void InputMethodAbility::OnRemoteSaDied(const wptr &object) isBound_.store(false); ClearInputControlChannel(); ClearSystemCmdChannel(); - { - std::lock_guard lock(abilityLock_); - abilityManager_ = nullptr; - } if (imeListener_ != nullptr) { imeListener_->OnInputStop(); } @@ -936,12 +868,7 @@ int32_t InputMethodAbility::GetSecurityMode(int32_t &security) security = securityMode; return ErrorCode::NO_ERROR; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("Imsa proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - auto ret = proxy->GetSecurityMode(security); + auto ret = ImaServiceProxy::GetInstance().GetSecurityMode(security); if (ret == ErrorCode::NO_ERROR) { securityMode_.store(security); } @@ -1254,14 +1181,9 @@ bool InputMethodAbility::IsCurrentIme() if (isCurrentIme_) { return true; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("failed to get imsa proxy!"); - return false; - } bool ret = false; - proxy->IsCurrentIme(ret); + ImaServiceProxy::GetInstance().IsCurrentIme(ret); if (ret) { isCurrentIme_ = true; } @@ -1278,14 +1200,10 @@ bool InputMethodAbility::IsDefaultIme() if (isDefaultIme_) { return true; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("failed to get imsa proxy!"); - return false; - } - auto ret = proxy->IsDefaultIme(); + bool isDefaultIme = false; + auto ret = ImaServiceProxy::GetInstance().IsDefaultIme(isDefaultIme); if (ret == ErrorCode::NO_ERROR) { - isDefaultIme_ = true; + isDefaultIme_ = isDefaultIme; return true; } IMSA_HILOGE("call IsDefaultIme failed, ret: %{public}d!", ret); @@ -1318,13 +1236,8 @@ bool InputMethodAbility::IsSystemApp() if (isSystemApp_) { return true; } - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("failed to get imsa proxy!"); - return false; - } bool ret = false; - proxy->IsSystemApp(ret); + ImaServiceProxy::GetInstance().IsSystemImeApp(ret); if (ret) { isSystemApp_ = true; } @@ -1335,12 +1248,7 @@ int32_t InputMethodAbility::ExitCurrentInputType() { IMSA_HILOGD("InputMethodAbility start."); ClearInputType(); - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("failed to get imsa proxy!"); - return false; - } - auto ret = proxy->ExitCurrentInputType(); + auto ret = ImaServiceProxy::GetInstance().ExitCurrentInputType(); if (ret == ErrorCode::NO_ERROR) { NotifyPanelStatus(false); } @@ -1838,13 +1746,7 @@ int32_t InputMethodAbility::OnResponse(uint64_t msgId, int32_t code, const Respo int32_t InputMethodAbility::IsCapacitySupport(int32_t capacity, bool &isSupport) { - auto proxy = GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("failed to get imsa proxy!"); - return ErrorCode::ERROR_NULL_POINTER; - } - - return proxy->IsCapacitySupport(capacity, isSupport); + return ImaServiceProxy::GetInstance().IsCapacitySupport(capacity, isSupport); } } // 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 2410b4b96e8d369d148f12dca471b7d49c539ede..aa92119c0b1b9efe2008c64561bf5533cc6f152b 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 @@ -25,7 +25,6 @@ namespace OHOS { namespace MiscServices { -using namespace MessageID; InputMethodAgentServiceImpl::InputMethodAgentServiceImpl() {} InputMethodAgentServiceImpl::~InputMethodAgentServiceImpl() {} diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp index 2b563cf6c3c387bc3c20eaa35eba7621a735fc68..281c176b88b26efbf86618872ef506d93c26cd23 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp @@ -30,7 +30,6 @@ namespace OHOS { namespace MiscServices { -using namespace MessageID; InputMethodCoreServiceImpl::InputMethodCoreServiceImpl() {} InputMethodCoreServiceImpl::~InputMethodCoreServiceImpl() {} diff --git a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp index d28fdae821b27117dfb6e57333f27da3baffa8f5..cda41123df672611db819bd7b8acbe96f28ca3ed 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp @@ -20,8 +20,8 @@ #include "display_info.h" #include "dm_common.h" #include "global.h" +#include "ima_service_proxy.h" #include "input_method_ability.h" -#include "input_method_ability_utils.h" #include "inputmethod_trace.h" #include "scene_board_judgement.h" #include "sys_cfg_parser.h" @@ -1490,11 +1490,6 @@ void InputMethodPanel::PanelStatusChangeToImc(const InputWindowStatus &status, c IMSA_HILOGD("no need to deal."); return; } - auto proxy = ImaUtils::GetImsaProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return; - } std::string name = window_->GetWindowName() + "/" + std::to_string(window_->GetWindowId()); info.windowInfo.name = std::move(name); info.windowInfo.left = rect.posX_; @@ -1504,7 +1499,7 @@ void InputMethodPanel::PanelStatusChangeToImc(const InputWindowStatus &status, c IMSA_HILOGD("rect[%{public}d, %{public}d, %{public}u, %{public}u], status: %{public}d, " "panelFlag: %{public}d.", rect.posX_, rect.posY_, rect.width_, rect.height_, status, info.panelInfo.panelFlag); - proxy->PanelStatusChange(static_cast(status), info); + ImaServiceProxy::GetInstance().PanelStatusChange(static_cast(status), info); } bool InputMethodPanel::IsShowing() diff --git a/frameworks/native/inputmethod_controller/IImcResponseChannel.idl b/frameworks/native/inputmethod_controller/IImcResponseChannel.idl new file mode 100644 index 0000000000000000000000000000000000000000..497fb83cbeb0d230abf66f2cc833354801ba4a74 --- /dev/null +++ b/frameworks/native/inputmethod_controller/IImcResponseChannel.idl @@ -0,0 +1,20 @@ +/* + * 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. + */ + +sequenceable service_response_data..OHOS.MiscServices.ServiceResponseDataInner; +interface OHOS.MiscServices.IImcResponseChannel { + [oneway] void OnResponse( + [in] unsigned int requestId, [in] int resultErrCode, [in] ServiceResponseDataInner response); +} diff --git a/frameworks/native/inputmethod_controller/IInputMethodSystemAbility.idl b/frameworks/native/inputmethod_controller/IInputMethodSystemAbility.idl index c12337039c3aa49af6f173cea5520cda97fc4eda..57e4746fadc4bc4a24ea2802bdc37930bb15bbda 100644 --- a/frameworks/native/inputmethod_controller/IInputMethodSystemAbility.idl +++ b/frameworks/native/inputmethod_controller/IInputMethodSystemAbility.idl @@ -23,52 +23,59 @@ sequenceable element_name..OHOS.AppExecFwk.ElementName; sequenceable OHOS.IRemoteObject; interface OHOS.MiscServices.IInputClient; interface OHOS.MiscServices.IInputMethodCore; +interface OHOS.MiscServices.IImaResponseChannel; +interface OHOS.MiscServices.IImcResponseChannel; interface OHOS.MiscServices.IInputMethodSystemAbility { - void StartInput([in] InputClientInfoInner inputClientInfoInner, - [out] IRemoteObject agent, [out] long pid, [out] String bundleName); - void ShowCurrentInput([in] unsigned int type); - void HideCurrentInput(); - void StopInputSession(); - void ShowInput([in] IInputClient client, [in] unsigned int type, [in] int requestKeyboardReason); - void HideInput([in] IInputClient client); - void ReleaseInput([in] IInputClient client, [in] unsigned int sessionId); - void RequestShowInput(); - void RequestHideInput([in] boolean isFocusTriggered); - void GetDefaultInputMethod([out] Property prop, [in] boolean isBrief); - void GetInputMethodConfig([out] ElementName inputMethodConfig); - void GetCurrentInputMethod([out] Property resultValue); - void GetCurrentInputMethodSubtype([out] SubProperty resultValue); - void ListInputMethod([in] unsigned int status, [out] Property[] props); - void DisplayOptionalInputMethod(); - void SetCoreAndAgent([in] IInputMethodCore core, [in] IRemoteObject agent); - void InitConnect(); - void UnRegisteredProxyIme([in] int type, [in] IInputMethodCore core); - void ListCurrentInputMethodSubtype([out] SubProperty[] subProps); - void ListInputMethodSubtype([in] String name, [out] SubProperty[] subProps); - void SwitchInputMethod([in] String bundleName, [in] String name, [in] unsigned int trigger); - [oneway] void PanelStatusChange([in] unsigned int status, [in] ImeWindowInfo info); - void UpdateListenEventFlag([in] InputClientInfoInner clientInfoInner, [in] unsigned int eventFlag); - void IsCurrentIme([out] boolean resultValue); - void IsInputTypeSupported([in] int type, [out] boolean resultValue); - void IsCurrentImeByPid([in] int pid, [out] boolean resultValue); - void StartInputType([in] int type); - void ExitCurrentInputType(); - void IsPanelShown([in] PanelInfo panelInfo, [out] boolean isShown); - void GetSecurityMode([out] int security); - void IsDefaultIme(); - void IsDefaultImeSet([out] boolean resultValue); - void EnableIme([in] String bundleName, [in] String extensionName, [in] int status); - void ConnectSystemCmd([in] IRemoteObject channel, [out] IRemoteObject agent); - void GetInputMethodState([out] int state); - void IsSystemApp([out] boolean resultValue); - void HideCurrentInputDeprecated(); - void ShowCurrentInputDeprecated(); - void SetCallingWindow([in] unsigned int windowId, [in] IInputClient client); - void GetInputStartInfo( - [out] boolean isInputStart, [out] unsigned int callingWndId, [out] int requestKeyboardReason); - void RegisterProxyIme([in] unsigned long displayId, [in] IInputMethodCore core, [in] IRemoteObject agent); - void UnregisterProxyIme([in] unsigned long displayId); - void SendPrivateData([in] Value value); - void IsDefaultImeScreen([in] unsigned long displayId, [out] boolean resultValue); - void IsCapacitySupport([in] int capacity, [out] boolean isSupport); + void RegisterImaResponseChannel([in] IImaResponseChannel channel); + void RegisterImcResponseChannel([in] IImcResponseChannel channel); + void StartInput([in] unsigned int requestId, [in] InputClientInfoInner inputClientInfoInner); + void ShowCurrentInput([in] unsigned int requestId, [in] unsigned int type); + void HideCurrentInput([in] unsigned int requestId); + void StopInputSession([in] unsigned int requestId); + void ShowInput( + [in] unsigned int requestId, [in] IInputClient client, [in] unsigned int type, [in] int requestKeyboardReason); + void HideInput([in] unsigned int requestId, [in] IInputClient client); + void ReleaseInput([in] unsigned int requestId, [in] IInputClient client, [in] unsigned int sessionId); + void RequestShowInput([in] unsigned int requestId); + void RequestHideInput([in] unsigned int requestId, [in] boolean isFocusTriggered); + void GetDefaultInputMethod([in] unsigned int requestId, [in] boolean isBrief); + void GetInputMethodConfig([in] unsigned int requestId); + void GetCurrentInputMethod([in] unsigned int requestId); + void GetCurrentInputMethodSubtype([in] unsigned int requestId); + void ListInputMethod([in] unsigned int requestId, [in] unsigned int status); + void DisplayOptionalInputMethod([in] unsigned int requestId); + void SetCoreAndAgent([in] unsigned int requestId, [in] IInputMethodCore core, [in] IRemoteObject agent); + void InitConnect([in] unsigned int requestId); + void UnRegisteredProxyIme([in] unsigned int requestId, [in] int type, [in] IInputMethodCore core); + void ListCurrentInputMethodSubtype([in] unsigned int requestId); + void ListInputMethodSubtype([in] unsigned int requestId, [in] String name); + void SwitchInputMethod( + [in] unsigned int requestId, [in] String bundleName, [in] String name, [in] unsigned int trigger); + [oneway] void PanelStatusChange([in] unsigned int requestId, [in] unsigned int status, [in] ImeWindowInfo info); + void UpdateListenEventFlag( + [in] unsigned int requestId, [in] InputClientInfoInner clientInfoInner, [in] unsigned int eventFlag); + void IsCurrentIme([in] unsigned int requestId); + void IsInputTypeSupported([in] unsigned int requestId, [in] int type); + void IsCurrentImeByPid([in] unsigned int requestId, [in] int pid); + void StartInputType([in] unsigned int requestId, [in] int type); + void ExitCurrentInputType([in] unsigned int requestId); + void IsPanelShown([in] unsigned int requestId, [in] PanelInfo panelInfo); + void GetSecurityMode([in] unsigned int requestId); + void IsDefaultIme([in] unsigned int requestId); + void IsDefaultImeSet([in] unsigned int requestId); + void EnableIme([in] unsigned int requestId, [in] String bundleName, [in] String extensionName, [in] int status); + void ConnectSystemCmd([in] unsigned int requestId, [in] IRemoteObject channel); + void GetInputMethodState([in] unsigned int requestId); + void IsSystemApp([in] unsigned int requestId); + void IsSystemImeApp([in] unsigned int requestId); + void HideCurrentInputDeprecated([in] unsigned int requestId); + void ShowCurrentInputDeprecated([in] unsigned int requestId); + void SetCallingWindow([in] unsigned int requestId, [in] unsigned int windowId, [in] IInputClient client); + void GetInputStartInfo([in] unsigned int requestId); + void RegisterProxyIme([in] unsigned int requestId, + [in] unsigned long displayId, [in] IInputMethodCore core, [in] IRemoteObject agent); + void UnregisterProxyIme([in] unsigned int requestId, [in] unsigned long displayId); + void SendPrivateData([in] unsigned int requestId, [in] Value value); + void IsDefaultImeScreen([in] unsigned int requestId, [in] unsigned long displayId); + void IsCapacitySupport([in] unsigned int requestId, [in] int capacity); } diff --git a/frameworks/native/inputmethod_controller/include/imc_response_channel_impl.h b/frameworks/native/inputmethod_controller/include/imc_response_channel_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..65102bd6778700f2b6f1b6ea08223b79d44be9cd --- /dev/null +++ b/frameworks/native/inputmethod_controller/include/imc_response_channel_impl.h @@ -0,0 +1,38 @@ +/* + * 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 IMF_IMC_RESPONSE_CHANNEL_IMPL_H +#define IMF_IMC_RESPONSE_CHANNEL_IMPL_H + +#include "iimc_response_channel.h" +#include "imc_response_channel_stub.h" +#include "iremote_object.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +class ImcResponseChannelImpl final + : public ImcResponseChannelStub + , public std::enable_shared_from_this { + DISALLOW_COPY_AND_MOVE(ImcResponseChannelImpl); + +public: + ImcResponseChannelImpl(); + ~ImcResponseChannelImpl(); + ErrCode OnResponse(uint32_t requestId, int32_t resultErrCode, const ServiceResponseDataInner &response) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // IMF_IMC_RESPONSE_CHANNEL_IMPL_H diff --git a/frameworks/native/inputmethod_controller/include/imc_service_proxy.h b/frameworks/native/inputmethod_controller/include/imc_service_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..9daedf56b3a1f9b85b43f62a80d7bb6d9aeb6703 --- /dev/null +++ b/frameworks/native/inputmethod_controller/include/imc_service_proxy.h @@ -0,0 +1,124 @@ +/* + * 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 IMF_IMC_SERVICE_PROXY_H +#define IMF_IMC_SERVICE_PROXY_H + +#include +#include +#include +#include + +#include "iimc_response_channel.h" +#include "iinput_method_system_ability.h" +#include "input_client_info.h" +#include "input_death_recipient.h" +#include "input_method_utils.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +class ImcServiceProxy { +private: + ImcServiceProxy(); + +public: + static ImcServiceProxy &GetInstance(); + + ~ImcServiceProxy() = default; + ImcServiceProxy(const ImcServiceProxy &) = delete; + ImcServiceProxy(ImcServiceProxy &&) = delete; + ImcServiceProxy &operator=(const ImcServiceProxy &) = delete; + ImcServiceProxy &operator=(ImcServiceProxy &&) = delete; + + int32_t SendRequest(const RequestFunc &request, int64_t timeout); + template + int32_t SendRequest(const RequestFunc &request, ResultType &resultValue, int64_t timeout); + + void OnResponse(RequestId id, const ServiceResponse &responseData); + + void RemoveDeathRecipient(); + + void Interrupt(); + void Resume(); + +private: + sptr TryGetSystemAbilityProxy(); + sptr GetSystemAbilityProxy(bool ifRetry = true); + void OnRemoteSaDied(const wptr &remote); + std::atomic hasRegistered_{ false }; + std::mutex abilityLock_{}; + sptr abilityManager_ = nullptr; + sptr deathRecipient_; + +public: + int32_t StartInput(InputClientInfo &inputClientInfo, StartInputResponse &response); + int32_t ShowCurrentInput(ClientType type); + int32_t HideCurrentInput(); + int32_t StopInputSession(); + int32_t ShowInput(sptr &client, ClientType type, int32_t requestKeyboardReason); + int32_t HideInput(sptr &client); + int32_t ReleaseInput(sptr client, uint32_t sessionId); + int32_t RequestShowInput(); + int32_t RequestHideInput(bool isFocusTriggered); + int32_t HideCurrentInputDeprecated(); + int32_t ShowCurrentInputDeprecated(); + + int32_t SwitchInputMethod(SwitchTrigger trigger, const std::string &name, const std::string &subName); + int32_t GetDefaultInputMethod(Property &property, bool isBrief); + int32_t GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig); + int32_t GetCurrentInputMethod(Property &resultValue); + int32_t GetCurrentInputMethodSubtype(SubProperty &resultValue); + int32_t GetInputMethodState(int32_t &status); + int32_t GetInputStartInfo(InputStartInfo &inputStartInfo); + int32_t ListInputMethod(InputMethodStatus status, std::vector &props); + int32_t ListCurrentInputMethodSubtype(std::vector &subProps); + int32_t ListInputMethodSubtype(const std::string &name, std::vector &subProps); + int32_t UpdateListenEventFlag(const InputClientInfoInner &inner, uint32_t eventFlag); + int32_t SetCallingWindow(uint32_t windowId, const sptr &client); + int32_t SendPrivateData(const Value &value); + int32_t DisplayOptionalInputMethod(); + + int32_t IsInputTypeSupported(int32_t type, bool &resultValue); + int32_t IsCurrentImeByPid(int32_t pid, bool &resultValue); + int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown); + int32_t IsDefaultImeSet(bool &resultValue); + int32_t IsSystemApp(bool &resultValue); + int32_t EnableIme(const std::string &bundleName, const std::string &extensionName, int32_t status); + + int32_t StartInputType(int32_t type); + int32_t ConnectSystemCmd(const sptr &channel, sptr &agent); + +private: + void Init(); + RequestId GetNextRequestId(); + int32_t RegisterResponseChannel(); + int32_t SendRequestInner(const RequestFunc &request, ServiceResponseData &responseData, int64_t timeout); + + void AddRequest(RequestId id, PendingRequest pendingRequest); + void RemoveRequest(RequestId requestId); + + std::mutex requestsMutex_{}; + std::unordered_map pendingRequests_; + std::atomic lastId_{ 0 }; + + sptr responseChannelStub_{ nullptr }; + std::atomic currentRequestId_{ 0 }; + std::atomic isInterrupted_{ false }; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_IMC_SERVICE_PROXY_H diff --git a/frameworks/native/inputmethod_controller/include/input_client_info.h b/frameworks/native/inputmethod_controller/include/input_client_info.h index b35768952c8792d3bf4a28e01f3e9f0a86157d5b..fdbac6793fce10f38dfcb235ab873016295cea56 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_info.h +++ b/frameworks/native/inputmethod_controller/include/input_client_info.h @@ -75,6 +75,8 @@ struct InputClientInfo { RequestKeyboardReason requestKeyboardReason { RequestKeyboardReason::NONE }; // show keyboard reason ClientType type{ INNER_KIT }; // for hiSysEvent std::string name; // for hiSysEvent, client name:SA/processName app/bundleName + + void UpdateInfoAboutBind(const InputClientInfo &info); }; struct InputClientInfoInner : public Parcelable { 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 785e993be354f7c9e67f6067fe21322e7f94f20c..eaa0dd3b2508866922caad4d08badc135d5edfb6 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 @@ -19,7 +19,6 @@ #include "iinput_data_channel.h" #include "input_data_channel_stub.h" #include "iremote_object.h" -#include "inputmethod_message_handler.h" namespace OHOS { namespace MiscServices { diff --git a/frameworks/native/inputmethod_controller/include/input_method_property.h b/frameworks/native/inputmethod_controller/include/input_method_property.h index 1b61e2a4b2deb7b7b1a3cd1fc3d8bc170aef57f8..3c086d0bd0f16c75318baefbfcdc6adb9a64e082 100644 --- a/frameworks/native/inputmethod_controller/include/input_method_property.h +++ b/frameworks/native/inputmethod_controller/include/input_method_property.h @@ -163,12 +163,11 @@ struct ImeInfo : public FullImeInfo { }; struct SwitchInfo { - std::chrono::system_clock::time_point timestamp{}; std::string bundleName; std::string subName; bool operator==(const SwitchInfo &info) const { - return (timestamp == info.timestamp && bundleName == info.bundleName && subName == info.subName); + return (bundleName == info.bundleName && subName == info.subName); } }; } // namespace MiscServices diff --git a/frameworks/native/inputmethod_controller/include/input_method_utils.h b/frameworks/native/inputmethod_controller/include/input_method_utils.h index a919161a4131e7c8bcc530fefcdfb64c25f2f326..90696dbaf2338d0c948816ea061a08388b37806a 100644 --- a/frameworks/native/inputmethod_controller/include/input_method_utils.h +++ b/frameworks/native/inputmethod_controller/include/input_method_utils.h @@ -556,6 +556,8 @@ struct ResponseDataInner : public Parcelable { } ResponseData rspData = std::monostate{}; }; + +enum class ImeLaunchType : uint32_t { LAUNCH_SKIPPED, ALREADY_LAUNCHED, NEEDS_LAUNCH }; } // namespace MiscServices } // namespace OHOS #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp b/frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp similarity index 43% rename from frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp rename to frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp index cd5e4393911f59a8840ad6d31a1e8e8316ebf7b0..e9c385b24916b22f4287317493b7e390727f2c1e 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp +++ b/frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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 @@ -13,31 +13,27 @@ * limitations under the License. */ -#include "input_method_ability_utils.h" +#include "imc_response_channel_impl.h" -#include "iservice_registry.h" -#include "on_demand_start_stop_sa.h" -#include "system_ability_definition.h" +#include "imc_service_proxy.h" namespace OHOS { namespace MiscServices { -std::mutex ImaUtils::abilityLock_; -sptr ImaUtils::abilityManager_ { nullptr }; // for tdd test -sptr ImaUtils::GetImsaProxy() + +ImcResponseChannelImpl::ImcResponseChannelImpl() +{ +} + +ImcResponseChannelImpl::~ImcResponseChannelImpl() +{ +} + +ErrCode ImcResponseChannelImpl::OnResponse( + uint32_t requestId, int32_t resultErrCode, const ServiceResponseDataInner &response) { - std::lock_guard lock(abilityLock_); - IMSA_HILOGD("ImaUtils::GetImsaProxy start."); - // for tdd test begin - if (abilityManager_ != nullptr) { - return abilityManager_; - } - // for tdd test end - auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(); - if (systemAbility == nullptr) { - IMSA_HILOGE("systemAbility is nullptr!"); - return nullptr; - } - return iface_cast(systemAbility); + ServiceResponse serviceResponse = { .result = resultErrCode, .responseData = response.data }; + ImcServiceProxy::GetInstance().OnResponse(requestId, serviceResponse); + return ERR_OK; } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp b/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e538a584bbd489b7c1265d1a28a2959e389e552d --- /dev/null +++ b/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp @@ -0,0 +1,768 @@ +/* + * 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 "imc_service_proxy.h" + +#include "imc_response_channel_impl.h" +#include "ime_system_channel.h" +#include "input_client_info.h" +#include "input_method_controller.h" +#include "input_method_tools.h" +#include "input_method_utils.h" +#include "on_demand_start_stop_sa.h" +#include "variant_util.h" + +namespace OHOS { +namespace MiscServices { +constexpr int64_t COMPLEX_REQUEST_TIMEOUT = 2000; +constexpr int64_t NORMAL_TIMEOUT = 1000; +constexpr int64_t QUERY_TIMEOUT = 100; +#define CHECK_RESPONSE_CHANNEL(retVal) \ + do { \ + auto ret = RegisterResponseChannel(); \ + if (ret != ErrorCode::NO_ERROR) { \ + IMSA_HILOGD("failed to register to sa, ret: %{public}d", ret); \ + return retVal; \ + } \ + } while (0) + +ImcServiceProxy &ImcServiceProxy::GetInstance() +{ + static ImcServiceProxy imcServiceProxy; + return imcServiceProxy; +} + +ImcServiceProxy::ImcServiceProxy() +{ + Init(); +} + +void ImcServiceProxy::Init() +{ + IMSA_HILOGD("start"); + sptr channel = new (std::nothrow) ImcResponseChannelImpl(); + if (channel == nullptr) { + IMSA_HILOGE("failed to create channel!"); + return; + } + responseChannelStub_ = channel; +} + +RequestId ImcServiceProxy::GetNextRequestId() +{ + static std::atomic seqId{ 1 }; + return seqId.fetch_add(1, std::memory_order_seq_cst); +} + +void ImcServiceProxy::OnResponse(RequestId id, const ServiceResponse &responseData) +{ + std::lock_guard lock(requestsMutex_); + auto iter = pendingRequests_.find(id); + if (iter == pendingRequests_.end()) { + IMSA_HILOGE("failed to find pending request, id: %{public}d", id); + return; + } + IMSA_HILOGD("id: %{public}d", id); + iter->second.promise.set_value(responseData); +} + +int32_t ImcServiceProxy::SendRequest(const RequestFunc &request, int64_t timeout) +{ + if (request == nullptr) { + IMSA_HILOGE("request is nullptr"); + return ErrorCode::ERROR_IMC_NULLPTR; + } + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + PendingRequest pendingRequest; + RequestId id = GetNextRequestId(); + auto future = pendingRequest.promise.get_future(); + AddRequest(id, std::move(pendingRequest)); + + // send request + int32_t ret = request(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("request failed, ret: %{public}d", ret); + RemoveRequest(id); + return ret; + } + + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + // wait till timeout + if (future.wait_for(std::chrono::milliseconds(timeout)) != std::future_status::ready) { + IMSA_HILOGE("service handle timeout"); + RemoveRequest(id); + return ErrorCode::ERROR_IMC_SERVICE_RESPONSE_TIMEOUT; + } + + // handle response + ServiceResponse response = future.get(); + ret = response.result; + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("task failed"); + return ret; + } + return ErrorCode::NO_ERROR; +} + +int32_t ImcServiceProxy::SendRequestInner( + const RequestFunc &request, ServiceResponseData &responseData, int64_t timeout) +{ + if (request == nullptr) { + IMSA_HILOGE("request is nullptr"); + return ErrorCode::ERROR_IMC_NULLPTR; + } + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + + PendingRequest pendingRequest; + RequestId id = GetNextRequestId(); + auto future = pendingRequest.promise.get_future(); + AddRequest(id, std::move(pendingRequest)); + + // send request + int32_t ret = request(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("request failed, ret: %{public}d", ret); + RemoveRequest(id); + return ret; + } + + if (isInterrupted_.load()) { + IMSA_HILOGW("request is interrupted"); + return ErrorCode::ERROR_REQUEST_INTERRUPTED; + } + // wait till timeout + if (future.wait_for(std::chrono::milliseconds(timeout)) != std::future_status::ready) { + IMSA_HILOGE("service handle timeout"); + RemoveRequest(id); + return ErrorCode::ERROR_IMC_SERVICE_RESPONSE_TIMEOUT; + } + + // handle response + ServiceResponse response = future.get(); + ret = response.result; + RemoveRequest(id); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("task failed"); + return ret; + } + responseData = response.responseData; + return ErrorCode::NO_ERROR; +} + +template +int32_t ImcServiceProxy::SendRequest(const RequestFunc &request, ResultType &resultValue, int64_t timeout) +{ + ServiceResponseData responseData; + int32_t ret = SendRequestInner(request, responseData, timeout); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + if (!VariantUtil::GetValue(responseData, resultValue)) { + IMSA_HILOGE("failed to get result value"); + return ErrorCode::ERROR_INVALID_VARIANT_TYPE; + } + return ErrorCode::NO_ERROR; +} + + +void ImcServiceProxy::OnRemoteSaDied(const wptr &remote) +{ + hasRegistered_.store(false); + ClearRequest(); + { + std::lock_guard lock(abilityLock_); + abilityManager_ = nullptr; + } + + // notify InputMethodController sa died + auto instance = InputMethodController::GetInstance(); + if (instance != nullptr) { + instance->OnRemoteSaDied(remote); + } + + // notify ImeSystemCmdChannel sa died + auto channel = ImeSystemCmdChannel::GetInstance(); + if (channel != nullptr) { + channel->OnRemoteSaDied(remote); + } +} + +void ImcServiceProxy::Interrupt() +{ + if (!isInterrupted_.exchange(true)) { + auto id = currentRequestId_.load(); + if (id == 0) { + return; + } + ServiceResponse response = { .result = ErrorCode::ERROR_REQUEST_INTERRUPTED }; + OnResponse(id, response); + } +} + +void ImcServiceProxy::Resume() +{ + isInterrupted_.store(false); +} + +sptr ImcServiceProxy::TryGetSystemAbilityProxy() +{ +#ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE + return GetSystemAbilityProxy(false); +#else + return GetSystemAbilityProxy(true); +#endif +} + +sptr ImcServiceProxy::GetSystemAbilityProxy(bool ifRetry) +{ + std::lock_guard lock(abilityLock_); + if (abilityManager_ != nullptr) { + return abilityManager_; + } + IMSA_HILOGD("get input method service proxy."); + auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(ifRetry); + if (systemAbility == nullptr) { + IMSA_HILOGE("systemAbility is nullptr!"); + return nullptr; + } + + if (deathRecipient_ == nullptr) { + deathRecipient_ = new (std::nothrow) InputDeathRecipient(); + if (deathRecipient_ == nullptr) { + IMSA_HILOGE("create death recipient failed!"); + return nullptr; + } + } + deathRecipient_->SetDeathRecipient([this](const wptr &remote) { OnRemoteSaDied(remote); }); + if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { + IMSA_HILOGE("failed to add death recipient!"); + return nullptr; + } + abilityManager_ = iface_cast(systemAbility); + return abilityManager_; +} + +void ImcServiceProxy::RemoveDeathRecipient() +{ + std::lock_guard lock(abilityLock_); + if (abilityManager_ != nullptr && abilityManager_->AsObject() != nullptr && deathRecipient_ != nullptr) { + abilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_); + } + deathRecipient_ = nullptr; + abilityManager_ = nullptr; +} + +void ImcServiceProxy::AddRequest(RequestId id, PendingRequest pendingRequest) +{ + std::lock_guard lock(requestsMutex_); + pendingRequests_[id] = std::move(pendingRequest); + currentRequestId_.store(id); +} + +void ImcServiceProxy::RemoveRequest(RequestId requestId) +{ + std::lock_guard lock(requestsMutex_); + pendingRequests_.erase(requestId); + currentRequestId_.store(0); +} + +int32_t ImcServiceProxy::RegisterResponseChannel() +{ + if (hasRegistered_.load()) { + return ErrorCode::NO_ERROR; + } + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get sa proxy"); + return ErrorCode::ERROR_IPC_REMOTE_NULLPTR; + } + return proxy->RegisterImcResponseChannel(responseChannelStub_); +} + +int32_t ImcServiceProxy::StartInput(InputClientInfo &inputClientInfo, StartInputResponse &response) +{ + RequestFunc request = [&inputClientInfo, this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + InputClientInfoInner clientInfoInner = InputMethodTools::GetInstance().InputClientInfoToInner(inputClientInfo); + return proxy->StartInput(requestId, clientInfoInner); + }; + return SendRequest(request, response, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImcServiceProxy::ShowCurrentInput(ClientType type) +{ + RequestFunc requestFunc = [type, this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ShowCurrentInput(requestId, static_cast(type)); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::HideCurrentInput() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->HideCurrentInput(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::StopInputSession() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->StopInputSession(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::ShowInput(sptr &client, ClientType type, int32_t requestKeyboardReason) +{ + RequestFunc requestFunc = [this, client, type, requestKeyboardReason](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ShowInput(requestId, client, type, requestKeyboardReason); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::HideInput(sptr &client) +{ + RequestFunc requestFunc = [this, client](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->HideInput(requestId, client); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::ReleaseInput(sptr client, uint32_t sessionId) +{ + RequestFunc requestFunc = [this, client, sessionId](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = TryGetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ReleaseInput(requestId, client, sessionId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::RequestShowInput() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->RequestShowInput(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::RequestHideInput(bool isFocusTriggered) +{ + RequestFunc requestFunc = [this, isFocusTriggered](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = TryGetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->RequestHideInput(requestId, isFocusTriggered); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::HideCurrentInputDeprecated() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->HideCurrentInputDeprecated(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::ShowCurrentInputDeprecated() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ShowCurrentInputDeprecated(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::GetDefaultInputMethod(Property &property, bool isBrief) +{ + RequestFunc requestFunc = [this, isBrief](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->GetDefaultInputMethod(requestId, isBrief); + }; + return SendRequest(requestFunc, property, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->GetInputMethodConfig(requestId); + }; + return SendRequest(requestFunc, inputMethodConfig, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::GetCurrentInputMethod(Property &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + proxy->GetCurrentInputMethod(requestId); + return ErrorCode::NO_ERROR; + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::GetCurrentInputMethodSubtype(SubProperty &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + proxy->GetCurrentInputMethodSubtype(requestId); + return ErrorCode::NO_ERROR; + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::GetInputMethodState(int32_t &status) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->GetInputMethodState(requestId); + }; + return SendRequest(requestFunc, status, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::GetInputStartInfo(InputStartInfo &inputStartInfo) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->GetInputStartInfo(requestId); + }; + return SendRequest(requestFunc, inputStartInfo, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::ListInputMethod(InputMethodStatus status, std::vector &props) +{ + RequestFunc requestFunc = [this, status](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ListInputMethod(requestId, status); + }; + return SendRequest(requestFunc, props, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::ListCurrentInputMethodSubtype(std::vector &subProps) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ListCurrentInputMethodSubtype(requestId); + }; + return SendRequest(requestFunc, subProps, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::ListInputMethodSubtype(const std::string &name, std::vector &subProps) +{ + RequestFunc requestFunc = [this, name](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ListInputMethodSubtype(requestId, name); + }; + return SendRequest(requestFunc, subProps, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::UpdateListenEventFlag(const InputClientInfoInner &inner, uint32_t eventFlag) +{ + RequestFunc requestFunc = [this, inner, eventFlag](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->UpdateListenEventFlag(requestId, inner, eventFlag); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::SetCallingWindow(uint32_t windowId, const sptr &client) +{ + RequestFunc requestFunc = [this, windowId, client](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->SetCallingWindow(requestId, windowId, client); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::SendPrivateData(const Value &value) +{ + RequestFunc requestFunc = [this, value](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->SendPrivateData(requestId, value); + }; + return SendRequest(requestFunc, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImcServiceProxy::DisplayOptionalInputMethod() +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->DisplayOptionalInputMethod(requestId); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::SwitchInputMethod(SwitchTrigger trigger, const std::string &name, const std::string &subName) +{ + RequestFunc requestFunc = [trigger, &name, &subName, this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->SwitchInputMethod(requestId, name, subName, static_cast(trigger)); + }; + return SendRequest(requestFunc, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImcServiceProxy::IsInputTypeSupported(int32_t type, bool &resultValue) +{ + RequestFunc requestFunc = [this, type](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsInputTypeSupported(requestId, type); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::IsCurrentImeByPid(int32_t pid, bool &resultValue) +{ + RequestFunc requestFunc = [this, pid](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsCurrentImeByPid(requestId, pid); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::IsPanelShown(const PanelInfo &panelInfo, bool &isShown) +{ + RequestFunc requestFunc = [this, panelInfo](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsDefaultIme(requestId); + }; + return SendRequest(requestFunc, isShown, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::IsDefaultImeSet(bool &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsDefaultIme(requestId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::IsSystemApp(bool &resultValue) +{ + RequestFunc requestFunc = [this](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->IsSystemApp(requestId); + }; + return SendRequest(requestFunc, resultValue, QUERY_TIMEOUT); +} + +int32_t ImcServiceProxy::EnableIme(const std::string &bundleName, const std::string &extensionName, int32_t status) +{ + RequestFunc requestFunc = [this, bundleName, extensionName, status](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->EnableIme(requestId, bundleName, extensionName, status); + }; + return SendRequest(requestFunc, NORMAL_TIMEOUT); +} + +int32_t ImcServiceProxy::StartInputType(int32_t type) +{ + RequestFunc requestFunc = [this, type](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->StartInputType(requestId, type); + }; + return SendRequest(requestFunc, COMPLEX_REQUEST_TIMEOUT); +} + +int32_t ImcServiceProxy::ConnectSystemCmd(const sptr &channel, sptr &agent) +{ + RequestFunc requestFunc = [this, channel](RequestId requestId) -> int32_t { + CHECK_RESPONSE_CHANNEL(ErrorCode::ERROR_IMC_NULLPTR); + auto proxy = GetSystemAbilityProxy(); + if (proxy == nullptr) { + IMSA_HILOGE("failed to get proxy"); + return ErrorCode::ERROR_SERVICE_START_FAILED; + } + return proxy->ConnectSystemCmd(requestId, channel); + }; + return SendRequest(requestFunc, agent, COMPLEX_REQUEST_TIMEOUT); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp b/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp index 40b4b585fea2984b51e0a9f57fd0095102e27357..2d398e9d01806ef486c3d66bc1afbf45070ccb26 100644 --- a/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp +++ b/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp @@ -18,11 +18,8 @@ #include "global.h" #include "input_method_agent_proxy.h" #include "input_method_controller.h" -#include "input_method_system_ability_proxy.h" -#include "iservice_registry.h" -#include "on_demand_start_stop_sa.h" -#include "system_ability_definition.h" #include "system_cmd_channel_service_impl.h" +#include "imc_service_proxy.h" namespace OHOS { namespace MiscServices { @@ -49,43 +46,9 @@ sptr ImeSystemCmdChannel::GetInstance() return instance_; } -sptr ImeSystemCmdChannel::GetSystemAbilityProxy() -{ - std::lock_guard lock(abilityLock_); - if (systemAbility_ != nullptr) { - return systemAbility_; - } - IMSA_HILOGI("get input method service proxy."); - auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(); - if (systemAbility == nullptr) { - IMSA_HILOGE("systemAbility is nullptr!"); - return nullptr; - } - if (deathRecipient_ == nullptr) { - deathRecipient_ = new (std::nothrow) InputDeathRecipient(); - if (deathRecipient_ == nullptr) { - IMSA_HILOGE("create death recipient failed!"); - return nullptr; - } - } - deathRecipient_->SetDeathRecipient([this](const wptr &remote) { - OnRemoteSaDied(remote); - }); - if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { - IMSA_HILOGE("failed to add death recipient!"); - return nullptr; - } - systemAbility_ = iface_cast(systemAbility); - return systemAbility_; -} - void ImeSystemCmdChannel::OnRemoteSaDied(const wptr &remote) { IMSA_HILOGI("input method service death."); - { - std::lock_guard lock(abilityLock_); - systemAbility_ = nullptr; - } ClearSystemCmdAgent(); } @@ -113,16 +76,11 @@ int32_t ImeSystemCmdChannel::RunConnectSystemCmd() } } - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } sptr agent = nullptr; static constexpr uint32_t RETRY_INTERVAL = 100; static constexpr uint32_t BLOCK_RETRY_TIMES = 5; - if (!BlockRetry(RETRY_INTERVAL, BLOCK_RETRY_TIMES, [&agent, this, proxy]() -> bool { - int32_t ret = proxy->ConnectSystemCmd(systemChannelStub_->AsObject(), agent); + if (!BlockRetry(RETRY_INTERVAL, BLOCK_RETRY_TIMES, [&agent, this]() -> bool { + int32_t ret = ImcServiceProxy::GetInstance().ConnectSystemCmd(systemChannelStub_->AsObject(), agent); return ret == ErrorCode::NO_ERROR; })) { IMSA_HILOGE("failed to connect system cmd!"); @@ -280,13 +238,8 @@ void ImeSystemCmdChannel::GetExtensionInfo( int32_t ImeSystemCmdChannel::GetDefaultImeCfg(std::shared_ptr &property) { IMSA_HILOGD("InputMethodAbility::GetDefaultImeCfg start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } Property prop; - auto ret = proxy->GetDefaultInputMethod(prop, true); + auto ret = ImcServiceProxy::GetInstance().GetDefaultInputMethod(prop, true); if (ret != ErrorCode::NO_ERROR) { return ret; } diff --git a/frameworks/native/inputmethod_controller/src/input_client_info.cpp b/frameworks/native/inputmethod_controller/src/input_client_info.cpp index 29db07f5f68030ff4d5b7166877788d33395e285..cc531ba9f7133165bf06046ab223c92eadfb3752 100644 --- a/frameworks/native/inputmethod_controller/src/input_client_info.cpp +++ b/frameworks/native/inputmethod_controller/src/input_client_info.cpp @@ -17,6 +17,19 @@ namespace OHOS { namespace MiscServices { +void InputClientInfo::UpdateInfoAboutBind(const InputClientInfo &info) +{ + isNotifyInputStart = info.isNotifyInputStart; + isShowKeyboard = info.isShowKeyboard; + needHide = info.needHide; + requestKeyboardReason = info.requestKeyboardReason; + config.requestKeyboardReason = info.requestKeyboardReason; + if (info.config.inputAttribute.IsSecurityImeFlag()) { + config.isSimpleKeyboardEnabled = false; + } else { + config.isSimpleKeyboardEnabled = info.config.isSimpleKeyboardEnabled; + } +} bool InputClientInfoInner::ReadFromParcel(Parcel &in) { 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 81376ca632ff4ed1b437b2a96bce76bedabe2c5e..a4fd1ab38a381973bcc3249dcd859eb6013095c5 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 @@ -21,7 +21,6 @@ #include "ipc_skeleton.h" #include "ipc_types.h" #include "itypes_util.h" -#include "message.h" #include "input_method_tools.h" namespace OHOS { namespace MiscServices { diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index 9fb6cbb38ced13d14ebbbae718f15904d1493f54..e41bfd04845ee2bbd895f24da98e7cbf9b9a8a5f 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -17,33 +17,29 @@ #include #include -#include "securec.h" #include "block_data.h" #include "global.h" #include "imc_hisysevent_reporter.h" +#include "imc_service_proxy.h" #include "ime_event_monitor_manager_impl.h" #include "input_client_service_impl.h" #include "input_data_channel_service_impl.h" #include "input_method_agent_proxy.h" #include "input_method_property.h" #include "input_method_status.h" -#include "input_method_system_ability_proxy.h" +#include "input_method_tools.h" #include "inputmethod_sysevent.h" #include "inputmethod_trace.h" -#include "iservice_registry.h" #include "keyevent_consumer_service_impl.h" -#include "on_demand_start_stop_sa.h" +#include "securec.h" #include "string_ex.h" #include "string_utils.h" #include "sys/prctl.h" -#include "system_ability_definition.h" #include "system_cmd_channel_stub.h" -#include "input_method_tools.h" namespace OHOS { namespace MiscServices { -using namespace MessageID; using namespace std::chrono; sptr InputMethodController::instance_; std::shared_ptr InputMethodController::handler_ { nullptr }; @@ -87,30 +83,17 @@ sptr InputMethodController::GetInstance() int32_t InputMethodController::RestoreListenEventFlag() { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } // 0 represent no need to check permission InputClientInfoInner infoInner = InputMethodTools::GetInstance().InputClientInfoToInner(clientInfo_); - return proxy->UpdateListenEventFlag(infoInner, 0); + return ImcServiceProxy::GetInstance().UpdateListenEventFlag(infoInner, 0); } int32_t InputMethodController::UpdateListenEventFlag(uint32_t finalEventFlag, uint32_t eventFlag, bool isOn) { auto oldEventFlag = clientInfo_.eventFlag; clientInfo_.eventFlag = finalEventFlag; - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - if (isOn) { - clientInfo_.eventFlag = oldEventFlag; - } - return ErrorCode::ERROR_SERVICE_START_FAILED; - } InputClientInfoInner infoInner = InputMethodTools::GetInstance().InputClientInfoToInner(clientInfo_); - auto ret = proxy->UpdateListenEventFlag(infoInner, eventFlag); + int32_t ret = ImcServiceProxy::GetInstance().UpdateListenEventFlag(infoInner, eventFlag); if (ret != ErrorCode::NO_ERROR && isOn) { clientInfo_.eventFlag = oldEventFlag; } @@ -146,54 +129,9 @@ int32_t InputMethodController::Initialize() return ErrorCode::NO_ERROR; } -sptr InputMethodController::TryGetSystemAbilityProxy() -{ -#ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE - return GetSystemAbilityProxy(false); -#else - return GetSystemAbilityProxy(true); -#endif -} - -sptr InputMethodController::GetSystemAbilityProxy(bool ifRetry) -{ - std::lock_guard lock(abilityLock_); - if (abilityManager_ != nullptr) { - return abilityManager_; - } - IMSA_HILOGD("get input method service proxy."); - auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(ifRetry); - if (systemAbility == nullptr) { - IMSA_HILOGE("systemAbility is nullptr!"); - return nullptr; - } - - if (deathRecipient_ == nullptr) { - deathRecipient_ = new (std::nothrow) InputDeathRecipient(); - if (deathRecipient_ == nullptr) { - IMSA_HILOGE("create death recipient failed!"); - return nullptr; - } - } - deathRecipient_->SetDeathRecipient([this](const wptr &remote) { - OnRemoteSaDied(remote); - }); - if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { - IMSA_HILOGE("failed to add death recipient!"); - return nullptr; - } - abilityManager_ = iface_cast(systemAbility); - return abilityManager_; -} - void InputMethodController::RemoveDeathRecipient() { - std::lock_guard lock(abilityLock_); - if (abilityManager_ != nullptr && abilityManager_->AsObject() != nullptr && deathRecipient_ != nullptr) { - abilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_); - } - deathRecipient_ = nullptr; - abilityManager_ = nullptr; + ImcServiceProxy::GetInstance().RemoveDeathRecipient(); } void InputMethodController::DeactivateClient() @@ -394,17 +332,12 @@ int32_t InputMethodController::HideCurrentInput() IMSA_HILOGD("not editable."); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } { std::lock_guard lock(clientInfoLock_); clientInfo_.isShowKeyboard = false; } InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL); - return proxy->HideCurrentInputDeprecated(); + return ImcServiceProxy::GetInstance().HideCurrentInputDeprecated(); } int32_t InputMethodController::ShowCurrentInput() @@ -414,18 +347,13 @@ int32_t InputMethodController::ShowCurrentInput() IMSA_HILOGD("not editable."); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGI("start."); { std::lock_guard lock(clientInfoLock_); clientInfo_.isShowKeyboard = true; } InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL); - return proxy->ShowCurrentInputDeprecated(); + return ImcServiceProxy::GetInstance().ShowCurrentInputDeprecated(); } int32_t InputMethodController::Close() @@ -458,35 +386,20 @@ void InputMethodController::Reset() int32_t InputMethodController::RequestShowInput() { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; // ERROR_EX_NULL_POINTER - } IMSA_HILOGI("InputMethodController start."); - return proxy->RequestShowInput(); + return ImcServiceProxy::GetInstance().RequestShowInput(); } int32_t InputMethodController::RequestHideInput(bool isFocusTriggered) { - auto proxy = TryGetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGD("InputMethodController start."); - return proxy->RequestHideInput(isFocusTriggered); + return ImcServiceProxy::GetInstance().RequestHideInput(isFocusTriggered); } int32_t InputMethodController::DisplayOptionalInputMethod() { IMSA_HILOGD("InputMethodController::DisplayOptionalInputMethod start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } - return proxy->DisplayOptionalInputMethod(); + return ImcServiceProxy::GetInstance().DisplayOptionalInputMethod(); } bool InputMethodController::WasAttached() @@ -497,23 +410,21 @@ bool InputMethodController::WasAttached() int32_t InputMethodController::GetInputStartInfo(bool &isInputStart, uint32_t &callingWndId, int32_t &requestKeyboardReason) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return false; + InputStartInfo info; + int32_t ret = ImcServiceProxy::GetInstance().GetInputStartInfo(info); + if (ret != ErrorCode::NO_ERROR) { + return ret; } - return proxy->GetInputStartInfo(isInputStart, callingWndId, requestKeyboardReason); + isInputStart = info.isInputStart; + callingWndId = info.callingWindowId; + requestKeyboardReason = info.requestKeyboardReason; + return ret; } int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector &props) { IMSA_HILOGD("InputMethodController::ListInputMethodCommon start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } - return proxy->ListInputMethod(status, props); + return ImcServiceProxy::GetInstance().ListInputMethod(status, props); } int32_t InputMethodController::ListInputMethod(std::vector &props) @@ -532,13 +443,8 @@ int32_t InputMethodController::GetDefaultInputMethod(std::shared_ptr & { InputMethodSyncTrace tracer("IMC_GetDefaultInputMethod"); IMSA_HILOGD("InputMethodController::GetDefaultInputMethod start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } Property prop; - auto ret = proxy->GetDefaultInputMethod(prop, false); + auto ret = ImcServiceProxy::GetInstance().GetDefaultInputMethod(prop, false); if (ret != ErrorCode::NO_ERROR) { return ret; } @@ -550,25 +456,15 @@ int32_t InputMethodController::GetInputMethodConfig(OHOS::AppExecFwk::ElementNam { InputMethodSyncTrace tracer("IMC_GetInputMethodConfig"); IMSA_HILOGD("InputMethodController::inputMethodConfig start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } - return proxy->GetInputMethodConfig(inputMethodConfig); + return ImcServiceProxy::GetInstance().GetInputMethodConfig(inputMethodConfig); } std::shared_ptr InputMethodController::GetCurrentInputMethod() { InputMethodSyncTrace tracer("IMC_GetCurrentInputMethod"); IMSA_HILOGD("InputMethodController::GetCurrentInputMethod start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return nullptr; - } Property propertyData; - proxy->GetCurrentInputMethod(propertyData); + ImcServiceProxy::GetInstance().GetCurrentInputMethod(propertyData); auto property = std::make_shared(propertyData); return property; } @@ -577,13 +473,8 @@ std::shared_ptr InputMethodController::GetCurrentInputMethodSubtype { InputMethodSyncTrace tracer("IMC_GetCurrentInputMethodSubtype"); IMSA_HILOGD("InputMethodController::GetCurrentInputMethodSubtype start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return nullptr; - } SubProperty subPropertyData; - proxy->GetCurrentInputMethodSubtype(subPropertyData); + ImcServiceProxy::GetInstance().GetCurrentInputMethodSubtype(subPropertyData); auto subProperty = std::make_shared(subPropertyData); return subProperty; } @@ -591,13 +482,8 @@ std::shared_ptr InputMethodController::GetCurrentInputMethodSubtype bool InputMethodController::IsDefaultImeSet() { IMSA_HILOGI("enter."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return false; - } bool ret = false; - proxy->IsDefaultImeSet(ret); + ImcServiceProxy::GetInstance().IsDefaultImeSet(ret); return ret; } @@ -605,37 +491,27 @@ int32_t InputMethodController::EnableIme( const std::string &bundleName, const std::string &extensionName, EnabledStatus status) { IMSA_HILOGI("enter."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return false; - } - return proxy->EnableIme(bundleName, extensionName, static_cast(status)); + return ImcServiceProxy::GetInstance().EnableIme(bundleName, extensionName, static_cast(status)); } int32_t InputMethodController::StartInput( InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo) { IMSA_HILOGD("InputMethodController::StartInput start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; + StartInputResponse response; + int32_t ret = ImcServiceProxy::GetInstance().StartInput(inputClientInfo, response); + if (ret != ErrorCode::NO_ERROR) { + return ret; } - InputClientInfoInner inner = InputMethodTools::GetInstance().InputClientInfoToInner(inputClientInfo); - int32_t ret = proxy->StartInput(inner, agent, imeInfo.first, imeInfo.second); + agent = response.agent; + imeInfo = { response.pid, response.bundleName }; return ret; } int32_t InputMethodController::ReleaseInput(sptr &client) { IMSA_HILOGD("InputMethodController::ReleaseInput start."); - auto proxy = TryGetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } - int32_t ret = proxy->ReleaseInput(client, sessionId_.load()); + int32_t ret = ImcServiceProxy::GetInstance().ReleaseInput(client, sessionId_.load()); if (ret == ErrorCode::NO_ERROR) { OnInputStop(); } @@ -646,23 +522,13 @@ int32_t InputMethodController::ReleaseInput(sptr &client) int32_t InputMethodController::ShowInput(sptr &client, ClientType type, int32_t requestKeyboardReason) { IMSA_HILOGD("InputMethodController::ShowInput start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } - return proxy->ShowInput(client, type, requestKeyboardReason); + return ImcServiceProxy::GetInstance().ShowInput(client, type, requestKeyboardReason); } int32_t InputMethodController::HideInput(sptr &client) { IMSA_HILOGD("InputMethodController::HideInput start."); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } - return proxy->HideInput(client); + return ImcServiceProxy::GetInstance().HideInput(client); } void InputMethodController::OnRemoteSaDied(const wptr &remote) @@ -675,10 +541,6 @@ void InputMethodController::OnRemoteSaDied(const wptr &remote) IMSA_HILOGD("finish text preview."); textListener->FinishTextPreviewV2(); } - { - std::lock_guard lock(abilityLock_); - abilityManager_ = nullptr; - } if (handler_ == nullptr) { IMSA_HILOGE("handler_ is nullptr!"); return; @@ -1052,102 +914,64 @@ int32_t InputMethodController::SetCallingWindow(uint32_t windowId) } IMSA_HILOGI("windowId: %{public}d.", windowId); agent->SetCallingWindow(windowId); - auto proxy = GetSystemAbilityProxy(); - if (proxy != nullptr) { - proxy->SetCallingWindow(windowId, clientInfo_.client); - } + ImcServiceProxy::GetInstance().SetCallingWindow(windowId, clientInfo_.client); return ErrorCode::NO_ERROR; } int32_t InputMethodController::ShowSoftKeyboardInner(ClientType type) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_SERVICE_START_FAILED; - } IMSA_HILOGI("start."); { std::lock_guard lock(clientInfoLock_); clientInfo_.isShowKeyboard = true; } InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL); - return proxy->ShowCurrentInput(type); + return ImcServiceProxy::GetInstance().ShowCurrentInput(type); } int32_t InputMethodController::HideSoftKeyboard() { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGI("start."); { std::lock_guard lock(clientInfoLock_); clientInfo_.isShowKeyboard = false; } InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL); - return proxy->HideCurrentInput(); + return ImcServiceProxy::GetInstance().HideCurrentInput(); } int32_t InputMethodController::StopInputSession() { IMSA_HILOGI("start."); isEditable_.store(false); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } - return proxy->StopInputSession(); + return ImcServiceProxy::GetInstance().StopInputSession(); } int32_t InputMethodController::ShowOptionalInputMethod() { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGI("IMC start."); - return proxy->DisplayOptionalInputMethod(); + return ImcServiceProxy::GetInstance().DisplayOptionalInputMethod(); } int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector &subProps) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGD("ime bundleName: %{public}s.", property.name.c_str()); - return proxy->ListInputMethodSubtype(property.name, subProps); + return ImcServiceProxy::GetInstance().ListInputMethodSubtype(property.name, subProps); } int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector &subProps) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGD("start."); - return proxy->ListCurrentInputMethodSubtype(subProps); + return ImcServiceProxy::GetInstance().ListCurrentInputMethodSubtype(subProps); } int32_t InputMethodController::SwitchInputMethod( SwitchTrigger trigger, const std::string &name, const std::string &subName) { InputMethodSyncTrace tracer("IMC_SwitchInputMethod"); - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_EX_NULL_POINTER; - } IMSA_HILOGI("name: %{public}s, subName: %{public}s, trigger: %{public}d.", name.c_str(), subName.c_str(), static_cast(trigger)); - return proxy->SwitchInputMethod(name, subName, static_cast(trigger)); + return ImcServiceProxy::GetInstance().SwitchInputMethod(trigger, name, subName); } int32_t InputMethodController::SetSimpleKeyboardEnabled(bool enable) @@ -1460,50 +1284,30 @@ int32_t InputMethodController::SendFunctionKey(int32_t functionKey) bool InputMethodController::IsInputTypeSupported(InputType type) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } IMSA_HILOGI("type: %{public}d.", static_cast(type)); bool ret = false; - proxy->IsInputTypeSupported(static_cast(type), ret); + ImcServiceProxy::GetInstance().IsInputTypeSupported(static_cast(type), ret); return ret; } bool InputMethodController::IsCurrentImeByPid(int32_t pid) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return false; - } bool ret = false; - proxy->IsCurrentImeByPid(pid, ret); + ImcServiceProxy::GetInstance().IsCurrentImeByPid(pid, ret); return ret; } int32_t InputMethodController::StartInputType(InputType type) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } IMSA_HILOGI("type: %{public}d.", static_cast(type)); - return proxy->StartInputType(static_cast(type)); + return ImcServiceProxy::GetInstance().StartInputType(static_cast(type)); } int32_t InputMethodController::IsPanelShown(const PanelInfo &panelInfo, bool &isShown) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } IMSA_HILOGD("type: %{public}d, flag: %{public}d.", static_cast(panelInfo.panelType), static_cast(panelInfo.panelFlag)); - return proxy->IsPanelShown(panelInfo, isShown); + return ImcServiceProxy::GetInstance().IsPanelShown(panelInfo, isShown); } void InputMethodController::SetAgent(const sptr &agentObject) @@ -1700,13 +1504,8 @@ std::shared_ptr InputMethodController::GetMsgHandle int32_t InputMethodController::GetInputMethodState(EnabledStatus &state) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } int32_t stateData = 0; - int32_t ret = proxy->GetInputMethodState(stateData); + int32_t ret = ImcServiceProxy::GetInstance().GetInputMethodState(stateData); state = static_cast(stateData); return ret; } @@ -1775,13 +1574,8 @@ void InputMethodController::UpdateTextPreviewState(bool isSupport) int32_t InputMethodController::SendPrivateData(const std::unordered_map &privateCommand) { - auto proxy = GetSystemAbilityProxy(); - if (proxy == nullptr) { - IMSA_HILOGE("proxy is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } Value value(privateCommand); - return proxy->SendPrivateData(value); + return ImcServiceProxy::GetInstance().SendPrivateData(value); } int32_t InputMethodController::RegisterWindowScaleCallbackHandler(WindowScaleCallback&& callback) diff --git a/frameworks/native/inputmethod_controller/src/system_cmd_channel_service_impl.cpp b/frameworks/native/inputmethod_controller/src/system_cmd_channel_service_impl.cpp index 74ac1deb1ebdd19362cbb9e2cc795a591d12697f..55b9fb4f4597b2c489e845f0e553f74dbdcab9b9 100644 --- a/frameworks/native/inputmethod_controller/src/system_cmd_channel_service_impl.cpp +++ b/frameworks/native/inputmethod_controller/src/system_cmd_channel_service_impl.cpp @@ -21,7 +21,6 @@ #include "ipc_skeleton.h" #include "ipc_types.h" #include "itypes_util.h" -#include "message.h" namespace OHOS { namespace MiscServices { diff --git a/interfaces/inner_api/inputmethod_ability/BUILD.gn b/interfaces/inner_api/inputmethod_ability/BUILD.gn index 00e193e07f5ab5e86ed370592dbd6cc915e46cb9..d3bba816f98d3de539721a117335a4a963529c40 100644 --- a/interfaces/inner_api/inputmethod_ability/BUILD.gn +++ b/interfaces/inner_api/inputmethod_ability/BUILD.gn @@ -50,10 +50,16 @@ idl_gen_interface("keyevent_consumer_interface") { "${inputmethod_path}/frameworks/native/inputmethod_controller/IKeyEventConsumer.idl") } +idl_gen_interface("ima_response_channel_interface") { + src_idl = rebase_path( + "${inputmethod_path}/frameworks/native/inputmethod_ability/IImaResponseChannel.idl") +} + config("inputmethod_ability_native_config") { visibility = [ ":*" ] include_dirs = [ "include", + "${inputmethod_path}/frameworks/native/common/include", "${inputmethod_path}/frameworks/native/inputmethod_ability/include", "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/frameworks/common", @@ -75,6 +81,7 @@ config("inputmethod_ability_native_public_config") { include_dirs = [ "include", "${inputmethod_path}/common/include", + "${inputmethod_path}/frameworks/native/common/include", "${inputmethod_path}/frameworks/native/inputmethod_ability/include", "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/frameworks/common", @@ -301,6 +308,48 @@ ohos_source_set("keyevent_consumer_stub") { part_name = "imf" } +ohos_source_set("ima_response_channel_proxy") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":inputmethod_ability_native_public_config" ] + output_values = get_target_outputs(":ima_response_channel_interface") + sources = filter_include(output_values, [ "*_proxy.cpp" ]) + deps = [ ":ima_response_channel_interface" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "input:libmmi-client", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + subsystem_name = "inputmethod" + part_name = "imf" +} + +ohos_source_set("ima_response_channel_stub") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":inputmethod_ability_native_public_config" ] + output_values = get_target_outputs(":ima_response_channel_interface") + sources = filter_include(output_values, [ "*_stub.cpp" ]) + deps = [ ":ima_response_channel_interface" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "input:libmmi-client", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + subsystem_name = "inputmethod" + part_name = "imf" +} + ohos_shared_library("inputmethod_ability") { branch_protector_ret = "pac_ret" sanitize = { @@ -312,10 +361,12 @@ ohos_shared_library("inputmethod_ability") { ubsan = true } sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_data_channel_proxy_wrap.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp", - "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_panel.cpp", @@ -363,6 +414,7 @@ ohos_shared_library("inputmethod_ability") { public_external_deps = [ "window_manager:libwm" ] deps = [ + ":ima_response_channel_interface", ":input_control_channel_interface", ":input_data_channel_interface", ":input_method_core_interface", @@ -432,6 +484,13 @@ ohos_shared_library("inputmethod_ability") { "*_stub.cpp", ]) + ima_response_channel_output_values = get_target_outputs(":ima_response_channel_interface") + sources += filter_include(ima_response_channel_output_values, + [ + "*_proxy.cpp", + "*_stub.cpp", + ]) + public_configs = [ ":inputmethod_ability_native_public_config" ] subsystem_name = "inputmethod" @@ -447,10 +506,12 @@ ohos_static_library("inputmethod_ability_static") { debug = false } sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_data_channel_proxy_wrap.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp", - "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_panel.cpp", @@ -489,6 +550,7 @@ ohos_static_library("inputmethod_ability_static") { public_external_deps = [ "window_manager:libwm" ] deps = [ + ":ima_response_channel_interface", ":input_control_channel_interface", ":input_data_channel_interface", ":input_method_core_interface", @@ -550,6 +612,13 @@ ohos_static_library("inputmethod_ability_static") { "*_stub.cpp", ]) + ima_response_channel_output_values = get_target_outputs(":ima_response_channel_interface") + sources += filter_include(ima_response_channel_output_values, + [ + "*_proxy.cpp", + "*_stub.cpp", + ]) + public_configs = [ ":inputmethod_ability_native_public_config" ] subsystem_name = "inputmethod" @@ -560,9 +629,11 @@ ohos_static_library("inputmethod_ability_fuzz_static") { branch_protector_ret = "pac_ret" sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_ability/src/ima_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp", - "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_ability_utils.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_agent_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_ability/src/input_method_panel.cpp", @@ -598,6 +669,7 @@ ohos_static_library("inputmethod_ability_fuzz_static") { public_external_deps = [ "window_manager:libwm" ] deps = [ + ":ima_response_channel_interface", ":input_control_channel_interface", ":input_data_channel_interface", ":input_method_core_interface", @@ -659,6 +731,13 @@ ohos_static_library("inputmethod_ability_fuzz_static") { "*_stub.cpp", ]) + ima_response_channel_output_values = get_target_outputs(":ima_response_channel_interface") + sources += filter_include(ima_response_channel_output_values, + [ + "*_proxy.cpp", + "*_stub.cpp", + ]) + public_configs = [ ":inputmethod_ability_native_public_config" ] subsystem_name = "inputmethod" diff --git a/interfaces/inner_api/inputmethod_controller/BUILD.gn b/interfaces/inner_api/inputmethod_controller/BUILD.gn index 073fcbae3996e067428861ef40d0cfc3f569fe1e..641967e864a981a7e1d9513ce3025a74477f1ed4 100644 --- a/interfaces/inner_api/inputmethod_controller/BUILD.gn +++ b/interfaces/inner_api/inputmethod_controller/BUILD.gn @@ -25,12 +25,18 @@ idl_gen_interface("input_method_agent_interface") { "${inputmethod_path}/frameworks/native/inputmethod_ability/IInputMethodAgent.idl") } +idl_gen_interface("imc_response_channel_interface") { + src_idl = rebase_path( + "${inputmethod_path}/frameworks/native/inputmethod_controller/IImcResponseChannel.idl") +} + config("inputmethod_client_native_config") { visibility = [ ":*" ] include_dirs = [ "include", "${inputmethod_path}/common/include", "${inputmethod_path}/frameworks/common", + "${inputmethod_path}/frameworks/native/common/include", "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller/include", "${inputmethod_path}/services/include", @@ -50,6 +56,7 @@ config("inputmethod_client_native_public_config") { "include", "${inputmethod_path}/common/include", "${inputmethod_path}/frameworks/common", + "${inputmethod_path}/frameworks/native/common/include", "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/frameworks/native/inputmethod_ability/include", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability/include", @@ -147,6 +154,48 @@ ohos_source_set("input_method_agent_proxy") { part_name = "imf" } +ohos_source_set("imc_response_channel_proxy") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":inputmethod_client_native_public_config" ] + output_values = get_target_outputs(":imc_response_channel_interface") + sources = filter_include(output_values, [ "*_proxy.cpp" ]) + deps = [ ":imc_response_channel_interface" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "input:libmmi-client", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + subsystem_name = "inputmethod" + part_name = "imf" +} + +ohos_source_set("imc_response_channel_stub") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":inputmethod_client_native_public_config" ] + output_values = get_target_outputs(":imc_response_channel_interface") + sources = filter_include(output_values, [ "*_stub.cpp" ]) + deps = [ ":imc_response_channel_interface" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "input:libmmi-client", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + subsystem_name = "inputmethod" + part_name = "imf" +} + ohos_shared_library("inputmethod_client") { branch_protector_ret = "pac_ret" @@ -159,6 +208,9 @@ ohos_shared_library("inputmethod_client") { ubsan = true } sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp", @@ -186,6 +238,7 @@ ohos_shared_library("inputmethod_client") { innerapi_tags = [ "platformsdk" ] deps = [ + ":imc_response_channel_interface", ":input_client_interface", ":input_method_agent_interface", "${inputmethod_path}/common:inputmethod_common", @@ -212,6 +265,13 @@ ohos_shared_library("inputmethod_client") { "*_stub.cpp", ]) + imc_response_channel_output_values = get_target_outputs(":imc_response_channel_interface") + sources += filter_include(imc_response_channel_output_values, + [ + "*_proxy.cpp", + "*_stub.cpp", + ]) + external_deps = [ "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", @@ -257,6 +317,9 @@ ohos_static_library("inputmethod_client_static") { ubsan = true } sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp", @@ -325,6 +388,9 @@ ohos_static_library("inputmethod_client_fuzz_static") { ubsan = true } sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_response_channel_impl.cpp", + "${inputmethod_path}/frameworks/native/inputmethod_controller/src/imc_service_proxy.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp", "${inputmethod_path}/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp", diff --git a/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h b/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h index db38c7d8f897df8b3acf6d311f69c765f29d13f3..f84b8488597d97bb6d81799ebbc260fbde17e32b 100644 --- a/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h +++ b/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h @@ -18,15 +18,15 @@ #include "bundle_mgr_client.h" #include "iinput_method_agent.h" -#include "iinput_method_system_ability.h" +#include "imc_service_proxy.h" #include "input_method_utils.h" #include "ipc_skeleton.h" #include "iremote_object.h" +#include "isystem_cmd_channel.h" #include "private_command_interface.h" #include "refbase.h" -#include "visibility.h" #include "sys_panel_status.h" -#include "isystem_cmd_channel.h" +#include "visibility.h" namespace OHOS { namespace MiscServices { @@ -90,12 +90,14 @@ public: void OnConnectCmdReady(const sptr &agentObject); IMF_API int32_t GetDefaultImeCfg(std::shared_ptr &property); +private: + friend ImcServiceProxy; + void OnRemoteSaDied(const wptr &object); + private: ImeSystemCmdChannel(); ~ImeSystemCmdChannel(); int32_t RunConnectSystemCmd(); - sptr GetSystemAbilityProxy(); - void OnRemoteSaDied(const wptr &object); void SetSystemCmdListener(const sptr &listener); sptr GetSystemCmdAgent(); sptr GetSystemCmdListener(); @@ -106,10 +108,6 @@ private: static std::mutex instanceLock_; static sptr instance_; - std::mutex abilityLock_; - sptr systemAbility_ = nullptr; - sptr deathRecipient_; - std::mutex systemCmdListenerLock_; sptr systemCmdListener_ = nullptr; 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 fe0611cec7073b70f32832f9eeb6593e7cd3384a..c7940a32118f0f9bfb64f3f436b02df34442e31f 100644 --- a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h +++ b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h @@ -30,7 +30,6 @@ #include "event_handler.h" #include "global.h" #include "iinput_method_agent.h" -#include "iinput_method_system_ability.h" #include "ime_event_listener.h" #include "input_client_info.h" #include "input_method_property.h" @@ -40,7 +39,6 @@ #include "iremote_object.h" #include "key_event.h" #include "msg_handler_callback_interface.h" -#include "inputmethod_message_handler.h" #include "panel_info.h" #include "private_command_interface.h" #include "visibility.h" @@ -981,13 +979,13 @@ public: void SetAgent(const sptr &agentObject); + void OnRemoteSaDied(const wptr &object); + private: InputMethodController(); ~InputMethodController(); int32_t Initialize(); - sptr GetSystemAbilityProxy(bool ifRetry = true); - sptr TryGetSystemAbilityProxy(); void RemoveDeathRecipient(); int32_t StartInput( InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo); @@ -997,7 +995,6 @@ private: int32_t ReleaseInput(sptr &client); int32_t ListInputMethodCommon(InputMethodStatus status, std::vector &props); void ClearEditorCache(bool isNewEditor, sptr lastListener); - void OnRemoteSaDied(const wptr &object); void RestoreListenInfoInSaDied(); void RestoreClientInfoInSaDied(); int32_t RestoreListenEventFlag(); @@ -1023,9 +1020,6 @@ private: friend class InputDataChannelServiceImpl; std::shared_ptr controllerListener_; - std::mutex abilityLock_; - sptr abilityManager_ = nullptr; - sptr deathRecipient_; std::mutex agentLock_; sptr agentObject_ = nullptr; std::shared_ptr agent_ = nullptr; diff --git a/services/BUILD.gn b/services/BUILD.gn index 7ae65c116d1d0277d446bebb463284a031a91001..8a3ea0a2541a4a16e21b00e5aa5fe903628e572f 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -20,7 +20,9 @@ config("inputmethod_services_native_config") { "include", "${inputmethod_path}/common/include", "${inputmethod_path}/frameworks/common", + "${inputmethod_path}/frameworks/native/common/include", "${inputmethod_path}/frameworks/native/inputmethod_ability/include", + "${inputmethod_path}/frameworks/native/inputmethod_ability/include/actions", "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability/include", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller/include", @@ -32,6 +34,9 @@ config("inputmethod_services_native_config") { "${inputmethod_path}/services/adapter/window_adapter/include", "${inputmethod_path}/services/adapter/wms_connection_monitor/include", "${inputmethod_path}/services/identity_checker/include", + "${inputmethod_path}/services/task_manager/include", + "${inputmethod_path}/services/task_manager/include/actions", + "${inputmethod_path}/services/task_manager/include/tasks", ] } @@ -55,6 +60,7 @@ ohos_shared_library("inputmethod_service") { "-Wno-c99-designator", ] sources = [ + "${inputmethod_path}/frameworks/native/common/src/service_response_data.cpp", "${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", @@ -68,6 +74,11 @@ ohos_shared_library("inputmethod_service") { "${inputmethod_path}/services/adapter/wms_connection_monitor/src/wms_connection_observer.cpp", "${inputmethod_path}/services/identity_checker/src/identity_checker_impl.cpp", "adapter/os_account_adapter/src/os_account_adapter.cpp", + "task_manager/src/requester_manager.cpp", + "task_manager/src/sa_task_manager.cpp", + "task_manager/src/actions/sa_action.cpp", + "task_manager/src/actions/sa_action_wait.cpp", + "task_manager/src/tasks/sa_task.cpp", "src/client_group.cpp", "src/freeze_manager.cpp", "src/full_ime_info_manager.cpp", @@ -92,9 +103,11 @@ ohos_shared_library("inputmethod_service") { deps = [ "${inputmethod_path}/common:inputmethod_common", "${inputmethod_path}/common/imf_hisysevent:imf_hisysevent", + "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:ima_response_channel_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_control_channel_stub", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_method_core_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_method_system_ability_stub", + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:imc_response_channel_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:input_client_proxy", "${inputmethod_path}/services/adapter/keyboard:keboard_event_static", "${inputmethod_path}/services/adapter/settings_data_provider:settings_data_static", @@ -176,6 +189,11 @@ ohos_static_library("inputmethod_service_static") { "adapter/window_adapter/src/window_display_changed_listener.cpp", "adapter/wms_connection_monitor/src/wms_connection_monitor_manager.cpp", "adapter/wms_connection_monitor/src/wms_connection_observer.cpp", + "task_manager/src/requester_manager.cpp", + "task_manager/src/sa_task_manager.cpp", + "task_manager/src/actions/sa_action.cpp", + "task_manager/src/actions/sa_action_wait.cpp", + "task_manager/src/tasks/sa_task.cpp", "identity_checker/src/identity_checker_impl.cpp", "src/client_group.cpp", "src/freeze_manager.cpp", @@ -197,9 +215,11 @@ ohos_static_library("inputmethod_service_static") { public_configs = [ ":inputmethod_services_native_config" ] deps = [ + "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:ima_response_channel_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_control_channel_stub", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_method_core_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_method_system_ability_stub", + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:imc_response_channel_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:input_client_proxy", ] diff --git a/services/adapter/focus_monitor/src/focus_change_listener.cpp b/services/adapter/focus_monitor/src/focus_change_listener.cpp index e8810241f4e8882682df0276b76e117bb8f352de..d2f96ea9a375791cb001d278861b52a2299a840b 100644 --- a/services/adapter/focus_monitor/src/focus_change_listener.cpp +++ b/services/adapter/focus_monitor/src/focus_change_listener.cpp @@ -18,6 +18,7 @@ #include #include "global.h" +#include "sa_task_manager.h" namespace OHOS { namespace MiscServices { @@ -27,9 +28,13 @@ void FocusChangedListener::OnFocused(const sptr &focusCh IMSA_HILOGE("error nullptr"); return; } - IMSA_HILOGD("displayId: %{public}" PRIu64 " pid: %{public}d, uid: %{public}d", focusChangeInfo->displayId_, - focusChangeInfo->pid_, focusChangeInfo->uid_); - focusHandle_(true, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_); + auto func = [focusChangeInfo, handler = focusHandle_](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGD("displayId: %{public}" PRIu64 " pid: %{public}d, uid: %{public}d", focusChangeInfo->displayId_, + focusChangeInfo->pid_, focusChangeInfo->uid_); + handler(true, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_FOCUSED, func)); } void FocusChangedListener::OnUnfocused(const sptr &focusChangeInfo) @@ -38,9 +43,13 @@ void FocusChangedListener::OnUnfocused(const sptr &focus IMSA_HILOGE("error nullptr"); return; } - IMSA_HILOGD("displayId: %{public}" PRIu64 " pid: %{public}d, uid: %{public}d", focusChangeInfo->displayId_, - focusChangeInfo->pid_, focusChangeInfo->uid_); - focusHandle_(false, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_); + auto func = [focusChangeInfo, handler = focusHandle_](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGD("displayId: %{public}" PRIu64 " pid: %{public}d, uid: %{public}d", focusChangeInfo->displayId_, + focusChangeInfo->pid_, focusChangeInfo->uid_); + handler(false, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_UNFOCUSED, func)); } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/adapter/settings_data_provider/BUILD.gn b/services/adapter/settings_data_provider/BUILD.gn index 2457812151cc2c5acab687b5c93ee045906c3150..8b367ed2c9df3a2ea3549eaefe4f10f4d2ebee4a 100644 --- a/services/adapter/settings_data_provider/BUILD.gn +++ b/services/adapter/settings_data_provider/BUILD.gn @@ -18,12 +18,17 @@ config("settings_data_config") { include_dirs = [ "include", "${inputmethod_path}/common/include", - "${inputmethod_path}/services/include", + "${inputmethod_path}/frameworks/native/common/include", + "${inputmethod_path}/frameworks/native/inputmethod_ability/include", + "${inputmethod_path}/frameworks/native/inputmethod_ability/include/actions", + "${inputmethod_path}/frameworks/native/inputmethod_controller/include", "${inputmethod_path}/services/adapter/os_account_adapter/include", "${inputmethod_path}/services/adapter/settings_data_provider/common/include", + "${inputmethod_path}/services/include", "${inputmethod_path}/services/json/include", - "${inputmethod_path}/frameworks/native/inputmethod_controller/include", - "${inputmethod_path}/frameworks/native/inputmethod_ability/include", + "${inputmethod_path}/services/task_manager/include", + "${inputmethod_path}/services/task_manager/include/actions", + "${inputmethod_path}/services/task_manager/include/tasks", ] } @@ -48,6 +53,8 @@ ohos_static_library("settings_data_static") { deps = [ "${inputmethod_path}/services/file:imf_file_static", "${inputmethod_path}/services/json:imf_json_static", + "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:input_data_channel_stub", + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:input_client_proxy", ] external_deps = [ "ability_base:zuri", diff --git a/services/adapter/settings_data_provider/include/ime_enabled_info_manager.h b/services/adapter/settings_data_provider/include/ime_enabled_info_manager.h index 0381b33cba0a2dcb9d2c4a2671f78eab2d930de1..2ca620bcb40858fcdc02d4dfc6e3d8348990c92d 100644 --- a/services/adapter/settings_data_provider/include/ime_enabled_info_manager.h +++ b/services/adapter/settings_data_provider/include/ime_enabled_info_manager.h @@ -116,11 +116,10 @@ struct ImeEnabledCfg : public Serializable { }; using CurrentImeStatusChangedHandler = std::function; -class ImeEnabledInfoManager { +class ImeEnabledInfoManager : public std::enable_shared_from_this { public: static ImeEnabledInfoManager &GetInstance(); void SetCurrentImeStatusChangedHandler(CurrentImeStatusChangedHandler handler); - void SetEventHandler(const std::shared_ptr &eventHandler); int32_t Init(const std::map> &fullImeInfos); int32_t Switch(int32_t userId, const std::vector &imeInfos); int32_t Delete(int32_t userId); diff --git a/services/adapter/settings_data_provider/src/ime_enabled_info_manager.cpp b/services/adapter/settings_data_provider/src/ime_enabled_info_manager.cpp index 918ce7a64af71aa96d97a43799a1dcb2ff7c7006..5ea63ddc943f0d69e6f1d95bef8738940a974e55 100644 --- a/services/adapter/settings_data_provider/src/ime_enabled_info_manager.cpp +++ b/services/adapter/settings_data_provider/src/ime_enabled_info_manager.cpp @@ -23,6 +23,8 @@ #include "enable_upgrade_manager.h" #include "ime_info_inquirer.h" +#include "sa_task_manager.h" + namespace OHOS { namespace MiscServices { using namespace std::chrono; @@ -44,11 +46,6 @@ void ImeEnabledInfoManager::SetCurrentImeStatusChangedHandler(CurrentImeStatusCh currentImeStatusChangedHandler_ = std::move(handler); } -void ImeEnabledInfoManager::SetEventHandler(const std::shared_ptr &eventHandler) -{ - serviceHandler_ = eventHandler; -} - int32_t ImeEnabledInfoManager::Init(const std::map> &fullImeInfos) { std::lock_guard lock(operateLock_); @@ -506,15 +503,16 @@ int32_t ImeEnabledInfoManager::UpdateEnabledCfgCache(int32_t userId, const ImeEn void ImeEnabledInfoManager::NotifyCurrentImeStatusChanged( int32_t userId, const std::string &bundleName, EnabledStatus newStatus) { - if (serviceHandler_ == nullptr) { - return; - } - auto notifyTask = [this, userId, bundleName, newStatus]() { - if (currentImeStatusChangedHandler_ != nullptr) { - currentImeStatusChangedHandler_(userId, bundleName, newStatus); + std::weak_ptr weakThis = shared_from_this(); + auto func = [weakThis, userId, bundleName, newStatus](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + if (sharedThis->currentImeStatusChangedHandler_ != nullptr) { + sharedThis->currentImeStatusChangedHandler_(userId, bundleName, newStatus); } + return ErrorCode::NO_ERROR; }; - serviceHandler_->PostTask(notifyTask, "NotifyCurrentImeStatusChanged", 0, AppExecFwk::EventQueue::Priority::VIP); + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_IME_ENABLED_STATE_CHANGED, func)); } bool ImeEnabledInfoManager::HasEnabledSwitch() @@ -573,15 +571,13 @@ bool ImeEnabledInfoManager::IsExpired(const std::string &expirationTime) void ImeEnabledInfoManager::UpdateGlobalEnabledTable(int32_t userId, const ImeEnabledCfg &newEnabledCfg) { - IMSA_HILOGD("start."); - if (serviceHandler_ == nullptr) { - return; - } - auto task = [userId, newEnabledCfg]() { + auto func = [userId, newEnabledCfg](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGD("start."); EnableUpgradeManager::GetInstance().UpdateGlobalEnabledTable(userId, newEnabledCfg); + IMSA_HILOGD("end."); + return ErrorCode::NO_ERROR; }; - serviceHandler_->PostTask(task, "UpdateGlobalEnabledTable", 0, AppExecFwk::EventQueue::Priority::LOW); - IMSA_HILOGD("end."); + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_UPDATE_GLOBAL_ENABLED_TABLE, func)); } void ImeEnabledInfoManager::OnFullExperienceTableChanged(int32_t userId) diff --git a/services/adapter/system_language_observer/src/system_language_observer.cpp b/services/adapter/system_language_observer/src/system_language_observer.cpp index 239954dd1775c2a03810aecad5b86af7de0d90a6..da476f496433167705359664906a9ce958473b78 100644 --- a/services/adapter/system_language_observer/src/system_language_observer.cpp +++ b/services/adapter/system_language_observer/src/system_language_observer.cpp @@ -14,8 +14,10 @@ */ #include "system_language_observer.h" -#include "inputmethod_message_handler.h" + #include "parameter.h" +#include "sa_task_manager.h" +#include "full_ime_info_manager.h" namespace OHOS { namespace MiscServices { @@ -38,11 +40,11 @@ void SystemLanguageObserver::OnChange(const char *key, const char *value, void * return; } IMSA_HILOGD("value: %{public}s.", value); - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_SYS_LANGUAGE_CHANGED, nullptr); - if (msg == nullptr) { - return; - } - MessageHandler::Instance()->SendMessage(msg); + SaActionFunc task = [](ServiceResponseData &, ActionInnerData &) { + FullImeInfoManager::GetInstance().Update(); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_SYSTEM_LANGUAGE_CHANGED, task)); } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/adapter/wms_connection_monitor/src/wms_connection_observer.cpp b/services/adapter/wms_connection_monitor/src/wms_connection_observer.cpp index c644912a632e4bbfee9daff78618bdf3b91f867c..6a4ef6edabc02ce37c8f9bf57633a7d78e8f5093 100644 --- a/services/adapter/wms_connection_monitor/src/wms_connection_observer.cpp +++ b/services/adapter/wms_connection_monitor/src/wms_connection_observer.cpp @@ -16,26 +16,42 @@ #include "wms_connection_observer.h" #include "global.h" +#include "sa_task_manager.h" + namespace OHOS { namespace MiscServices { std::mutex WmsConnectionObserver::lock_; std::set WmsConnectionObserver::connectedUserId_; void WmsConnectionObserver::OnConnected(int32_t userId, int32_t screenId) { - IMSA_HILOGI("WMS connect, userId: %{public}d, screenId: %{public}d.", userId, screenId); + IMSA_HILOGD("WMS connect, userId: %{public}d, screenId: %{public}d.", userId, screenId); Add(userId); - if (changeHandler_ != nullptr) { - changeHandler_(true, userId, screenId); + if (changeHandler_ == nullptr) { + return; } + auto func = [userId, screenId, handler = changeHandler_](ServiceResponseData &, ActionInnerData &) { + if (handler != nullptr) { + handler(true, userId, screenId); + } + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_WMS_CONNECTED, func)); } void WmsConnectionObserver::OnDisconnected(int32_t userId, int32_t screenId) { - IMSA_HILOGI("WMS disconnect, userId: %{public}d, screenId: %{public}d.", userId, screenId); + IMSA_HILOGD("WMS disconnect, userId: %{public}d, screenId: %{public}d.", userId, screenId); Remove(userId); - if (changeHandler_ != nullptr) { - changeHandler_(false, userId, screenId); + if (changeHandler_ == nullptr) { + return; } + auto func = [userId, screenId, handler = changeHandler_](ServiceResponseData &, ActionInnerData &) { + if (handler != nullptr) { + handler(false, userId, screenId); + } + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_WMS_DISCONNECTED, func)); } void WmsConnectionObserver::Add(int32_t userId) diff --git a/services/identity_checker/include/identity_checker.h b/services/identity_checker/include/identity_checker.h index 0d9f0d2faddf255b1d6651f51afd87af9e5a261a..67dbdb33e87541a3853aa9a9215f5b296576d14c 100644 --- a/services/identity_checker/include/identity_checker.h +++ b/services/identity_checker/include/identity_checker.h @@ -50,7 +50,7 @@ public: { return false; }; - virtual bool IsSpecialSaUid() = 0; + virtual bool IsSpecialSaUid(int32_t callingUid) = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/identity_checker/include/identity_checker_impl.h b/services/identity_checker/include/identity_checker_impl.h index d7bc6752d4d78b2a98940d6956dece59b0dff942..e6e13619c28693623c2f47d08e551c83fcd1061b 100644 --- a/services/identity_checker/include/identity_checker_impl.h +++ b/services/identity_checker/include/identity_checker_impl.h @@ -35,7 +35,7 @@ public: uint64_t GetDisplayIdByWindowId(int32_t callingWindowId) override; uint64_t GetDisplayIdByPid(int64_t callingPid, sptr abilityToken = nullptr) override; bool IsValidVirtualIme(int32_t callingUid) override; - bool IsSpecialSaUid() override; + bool IsSpecialSaUid(int32_t callingUid) override; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/identity_checker/src/identity_checker_impl.cpp b/services/identity_checker/src/identity_checker_impl.cpp index eb62d9de19f19ce0fd43fe0ca3c2281ef2c43fb8..9df99615ea5d04778ee2856afd89fbed718c214c 100644 --- a/services/identity_checker/src/identity_checker_impl.cpp +++ b/services/identity_checker/src/identity_checker_impl.cpp @@ -171,9 +171,8 @@ bool IdentityCheckerImpl::IsValidVirtualIme(int32_t callingUid) return ImeInfoInquirer::GetInstance().IsVirtualProxyIme(callingUid); } -bool IdentityCheckerImpl::IsSpecialSaUid() +bool IdentityCheckerImpl::IsSpecialSaUid(int32_t callingUid) { - auto callingUid = IPCSkeleton::GetCallingUid(); return ImeInfoInquirer::GetInstance().IsSpecialSaUid(callingUid); } } // namespace MiscServices diff --git a/services/include/im_common_event_manager.h b/services/include/im_common_event_manager.h index e0ef404fc93fdd3a3a471ea1f9ed0edc4bf0da8e..4f3aef3fb904b90073afa108cd5a61cc1173a46b 100644 --- a/services/include/im_common_event_manager.h +++ b/services/include/im_common_event_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -25,40 +25,40 @@ namespace OHOS { namespace MiscServices { using Handler = std::function; +using CommonEventHandler = std::function; class ImCommonEventManager : public RefBase { +private: + ImCommonEventManager() = default; + public: - ImCommonEventManager(); - ~ImCommonEventManager(); - static sptr GetInstance(); - bool SubscribeEvent(); - bool SubscribeKeyboardEvent(const Handler &handler); - bool SubscribeWindowManagerService(const Handler &handler); - bool SubscribeMemMgrService(const Handler &handler); - bool SubscribeAccountManagerService(Handler handle); - bool SubscribePasteboardService(const Handler &handler); - bool UnsubscribeEvent(); + static ImCommonEventManager &GetInstance(); + + ~ImCommonEventManager() = default; + ImCommonEventManager(const ImCommonEventManager &) = delete; + ImCommonEventManager(ImCommonEventManager &&) = delete; + ImCommonEventManager &operator=(const ImCommonEventManager &) = delete; + ImCommonEventManager &operator=(ImCommonEventManager &&) = delete; + + bool SubscribeEvents(); + void SubscribeSaStatus(); + void RegisterEventHandler(const std::string &eventName, const CommonEventHandler &handler); + void RegisterSaHandler(int32_t saId, const Handler &handler); + // only public the status change of softKeyboard in FLG_FIXED or FLG_FLOATING int32_t PublishPanelStatusChangeEvent(int32_t userId, const InputWindowStatus &status, const ImeWindowInfo &info); + class EventSubscriber : public EventFwk::CommonEventSubscriber { public: - EventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + EventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) : CommonEventSubscriber(subscribeInfo) + { + } void OnReceiveEvent(const EventFwk::CommonEventData &data); - void RemovePackage(const EventFwk::CommonEventData &data); - void StartUser(const EventFwk::CommonEventData &data); - void RemoveUser(const EventFwk::CommonEventData &data); - void StopUser(const EventFwk::CommonEventData &data); - void OnBundleScanFinished(const EventFwk::CommonEventData &data); - void OnDataShareReady(const EventFwk::CommonEventData &data); - void AddPackage(const EventFwk::CommonEventData &data); - void ChangePackage(const EventFwk::CommonEventData &data); - void HandleBootCompleted(const EventFwk::CommonEventData &data); - void OnScreenUnlock(const EventFwk::CommonEventData &data); + void SetHandlers(std::unordered_map handlers); private: - using EventListenerFunc = std::function; - std::map EventManagerFunc_; - void HandlePackageEvent(int32_t messageId, const EventFwk::CommonEventData &data); - void HandleUserEvent(int32_t messageId, const EventFwk::CommonEventData &data); + CommonEventHandler GetHandler(const std::string &event); + std::mutex handlersMutex_; + std::unordered_map commonEventHandlers_; }; private: @@ -75,8 +75,12 @@ private: }; private: - static std::mutex instanceLock_; - static sptr instance_; + std::mutex eventMutex_; + std::unordered_map eventHandlers_; + + Handler GetServiceHandler(); + std::mutex serviceMutex_; + std::unordered_map serviceHandlers_; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/include/ime_cfg_manager.h b/services/include/ime_cfg_manager.h index fd0e6ad9223390d77e53255e04364dd7a5571aaa..f23aa75b7b1bc032803b0bcbea93924912333c93 100644 --- a/services/include/ime_cfg_manager.h +++ b/services/include/ime_cfg_manager.h @@ -22,7 +22,6 @@ #include "serializable.h" #include "ime_enabled_info_manager.h" #include "enable_upgrade_manager.h" -#include "event_handler.h" namespace OHOS { namespace MiscServices { @@ -33,22 +32,18 @@ public: void AddImeCfg(const ImePersistInfo &cfg); void ModifyImeCfg(const ImePersistInfo &cfg); void ModifyTempScreenLockImeCfg(int32_t userId, const std::string &ime); - void DeleteImeCfg(int32_t userId); std::shared_ptr GetCurrentImeCfg(int32_t userId); bool IsDefaultImeSet(int32_t userId); - void SetEventHandler(const std::shared_ptr &eventHandler); private: ImeCfgManager() = default; ~ImeCfgManager() = default; void ReadImeCfg(); - void WriteImeCfg(); ImePersistInfo GetImeCfg(int32_t userId); bool ParseImeCfg(const std::string &content); std::string PackageImeCfg(); std::recursive_mutex imeCfgLock_; std::vector imeConfigs_; - static std::shared_ptr serviceHandler_; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/include/ime_lifecycle_manager.h b/services/include/ime_lifecycle_manager.h index d8c2a6fc5668d0c0cc2c64f608334107d711e371..7653f454d47d468263bf56e77781556962fb940b 100644 --- a/services/include/ime_lifecycle_manager.h +++ b/services/include/ime_lifecycle_manager.h @@ -39,6 +39,7 @@ public: private: void ControlIme(bool shouldApply) override; + void OnStopIme(); std::function stopImeFunc_; int32_t stopDelayTime_ { STOP_DELAY_TIME }; constexpr static int32_t STOP_DELAY_TIME = 20000; diff --git a/services/include/input_control_channel_service_impl.h b/services/include/input_control_channel_service_impl.h index 8fbc6e6e4af8b0e367bd12e010776e0598c38eb5..24fb6e18ac8bfd403d32c4aa161200329435f9d0 100644 --- a/services/include/input_control_channel_service_impl.h +++ b/services/include/input_control_channel_service_impl.h @@ -21,7 +21,6 @@ #include "iinput_control_channel.h" #include "input_control_channel_stub.h" #include "iremote_object.h" -#include "inputmethod_message_handler.h" namespace OHOS { namespace MiscServices { diff --git a/services/include/input_method_system_ability.h b/services/include/input_method_system_ability.h index d931891719921524c6247ea99f0746b5defb4698..7f20ce90984071a2c4b98150a48eaa908dc22e01 100644 --- a/services/include/input_method_system_ability.h +++ b/services/include/input_method_system_ability.h @@ -16,20 +16,25 @@ #ifndef SERVICES_INCLUDE_INPUT_METHOD_SYSTEM_ABILITY_H #define SERVICES_INCLUDE_INPUT_METHOD_SYSTEM_ABILITY_H +#include "caller_info.h" +#include "common_event_manager.h" #include "identity_checker_impl.h" #include "ime_info_inquirer.h" #include "input_method_system_ability_stub.h" +#include "input_method_types.h" +#include "input_type_manager.h" #include "inputmethod_dump.h" #include "inputmethod_trace.h" #include "system_ability.h" -#include "input_method_types.h" #include "user_session_manager.h" -#include "input_type_manager.h" namespace OHOS { namespace MiscServices { enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; -class InputMethodSystemAbility : public SystemAbility, public InputMethodSystemAbilityStub { +class InputMethodSystemAbility + : public SystemAbility + , public InputMethodSystemAbilityStub + , public std::enable_shared_from_this { DECLARE_SYSTEM_ABILITY(InputMethodSystemAbility); public: @@ -39,59 +44,65 @@ public: ~InputMethodSystemAbility(); int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; - ErrCode StartInput(const InputClientInfoInner &inputClientInfoInner, sptr &agent, - int64_t &pid, std::string &bundleName) override; - ErrCode ShowCurrentInput(uint32_t type = static_cast(ClientType::INNER_KIT)) override; - ErrCode HideCurrentInput() override; - ErrCode ShowInput(const sptr& client, uint32_t type = static_cast(ClientType::INNER_KIT), - int32_t requestKeyboardReason = 0) override; - ErrCode HideInput(const sptr& client) override; - ErrCode StopInputSession() override; - ErrCode ReleaseInput(const sptr& client, uint32_t sessionId) override; - ErrCode RequestShowInput() override; - ErrCode RequestHideInput(bool isFocusTriggered) override; - ErrCode GetDefaultInputMethod(Property &prop, bool isBrief) override; - ErrCode GetInputMethodConfig(ElementName &inputMethodConfig) override; - ErrCode GetCurrentInputMethod(Property& resultValue) override; - ErrCode GetCurrentInputMethodSubtype(SubProperty& resultValue) override; - ErrCode ListInputMethod(uint32_t status, std::vector &props) override; - ErrCode ListCurrentInputMethodSubtype(std::vector &subProps) override; - ErrCode ListInputMethodSubtype(const std::string &bundleName, std::vector &subProps) override; + ErrCode RegisterImaResponseChannel(const sptr &channel) override; + ErrCode RegisterImcResponseChannel(const sptr &channel) override; + ErrCode StartInput(uint32_t requestId, const InputClientInfoInner &inputClientInfoInner) override; + ErrCode ShowCurrentInput(uint32_t requestId, uint32_t type = static_cast(ClientType::INNER_KIT)) override; + ErrCode HideCurrentInput(uint32_t requestId) override; + ErrCode ShowInput(uint32_t requestId, const sptr &client, + uint32_t type = static_cast(ClientType::INNER_KIT), int32_t requestKeyboardReason = 0) override; + ErrCode HideInput(uint32_t requestId, const sptr &client) override; + ErrCode StopInputSession(uint32_t requestId) override; + ErrCode ReleaseInput(uint32_t requestId, const sptr &client, uint32_t sessionId) override; + ErrCode RequestShowInput(uint32_t requestId) override; + ErrCode RequestHideInput(uint32_t requestId, bool isFocusTriggered) override; + ErrCode GetDefaultInputMethod(uint32_t requestId, bool isBrief) override; + ErrCode GetInputMethodConfig(uint32_t requestId) override; + ErrCode GetCurrentInputMethod(uint32_t requestId) override; + ErrCode GetCurrentInputMethodSubtype(uint32_t requestId) override; + ErrCode ListInputMethod(uint32_t requestId, uint32_t status) override; + ErrCode ListCurrentInputMethodSubtype(uint32_t requestId) override; + ErrCode ListInputMethodSubtype(uint32_t requestId, const std::string &bundleName) override; ErrCode SwitchInputMethod( - const std::string &bundleName, const std::string &subName, uint32_t trigger) override; - ErrCode DisplayOptionalInputMethod() override; - ErrCode SetCoreAndAgent(const sptr &core, const sptr &agent) override; - ErrCode InitConnect() override; - ErrCode UnRegisteredProxyIme(int32_t type, const sptr &core) override; - ErrCode PanelStatusChange(uint32_t status, const ImeWindowInfo &info) override; - ErrCode UpdateListenEventFlag(const InputClientInfoInner &clientInfoInner, uint32_t eventFlag) override; - ErrCode SetCallingWindow(uint32_t windowId, const sptr& client) override; - ErrCode GetInputStartInfo(bool& isInputStart, uint32_t& callingWndId, int32_t& requestKeyboardReason) override; - ErrCode SendPrivateData(const Value &value) override; + uint32_t requestId, const std::string &bundleName, const std::string &subName, uint32_t trigger) override; + ErrCode DisplayOptionalInputMethod(uint32_t requestId) override; + ErrCode SetCoreAndAgent( + uint32_t requestId, const sptr &core, const sptr &agent) override; + ErrCode InitConnect(uint32_t requestId) override; + ErrCode UnRegisteredProxyIme(uint32_t requestId, int32_t type, const sptr &core) override; + ErrCode PanelStatusChange(uint32_t requestId, uint32_t status, const ImeWindowInfo &info) override; + ErrCode UpdateListenEventFlag( + uint32_t requestId, const InputClientInfoInner &clientInfoInner, uint32_t eventFlag) override; + ErrCode SetCallingWindow(uint32_t requestId, uint32_t windowId, const sptr &client) override; + ErrCode GetInputStartInfo(uint32_t requestId) override; + ErrCode SendPrivateData(uint32_t requestId, const Value &value) override; - ErrCode IsCurrentIme(bool& resultValue) override; - ErrCode IsInputTypeSupported(int32_t type, bool& resultValue) override; - ErrCode IsCurrentImeByPid(int32_t pid, bool& resultValue) override; - ErrCode StartInputType(int32_t type) override; - ErrCode ExitCurrentInputType() override; - ErrCode IsPanelShown(const PanelInfo &panelInfo, bool &isShown) override; - ErrCode GetSecurityMode(int32_t &security) override; - ErrCode ConnectSystemCmd(const sptr &channel, sptr &agent) override; + ErrCode IsCurrentIme(uint32_t requestId) override; + ErrCode IsInputTypeSupported(uint32_t requestId, int32_t type) override; + ErrCode IsCurrentImeByPid(uint32_t requestId, int32_t pid) override; + ErrCode StartInputType(uint32_t requestId, int32_t type) override; + ErrCode ExitCurrentInputType(uint32_t requestId) override; + ErrCode IsPanelShown(uint32_t requestId, const PanelInfo &panelInfo) override; + ErrCode GetSecurityMode(uint32_t requestId) override; + ErrCode ConnectSystemCmd(uint32_t requestId, const sptr &channel) override; // Deprecated because of no permission check, kept for compatibility - ErrCode HideCurrentInputDeprecated() override; - ErrCode ShowCurrentInputDeprecated() override; + ErrCode HideCurrentInputDeprecated(uint32_t requestId) override; + ErrCode ShowCurrentInputDeprecated(uint32_t requestId) override; + ErrCode IsDefaultIme(uint32_t requestId) override; + ErrCode IsDefaultImeSet(uint32_t requestId) override; + ErrCode EnableIme( + uint32_t requestId, const std::string &bundleName, const std::string &extensionName, int32_t status) override; + ErrCode GetInputMethodState(uint32_t requestId) override; + ErrCode IsSystemApp(uint32_t requestId) override; + ErrCode IsSystemImeApp(uint32_t requestId) override; + ErrCode RegisterProxyIme(uint32_t requestId, uint64_t displayId, const sptr &core, + const sptr &agent) override; + ErrCode UnregisterProxyIme(uint32_t requestId, uint64_t displayId) override; + ErrCode IsDefaultImeScreen(uint32_t requestId, uint64_t displayId) override; + ErrCode IsCapacitySupport(uint32_t requestId, int32_t capacity) override; + int Dump(int fd, const std::vector &args) override; void DumpAllMethod(int fd); - ErrCode IsDefaultIme() override; - ErrCode IsDefaultImeSet(bool& resultValue) override; - ErrCode EnableIme(const std::string &bundleName, const std::string &extensionName, int32_t status) override; - ErrCode GetInputMethodState(int32_t &status) override; - ErrCode IsSystemApp(bool& resultValue) override; - int32_t RegisterProxyIme( - uint64_t displayId, const sptr &core, const sptr &agent) override; - int32_t UnregisterProxyIme(uint64_t displayId) override; - ErrCode IsDefaultImeScreen(uint64_t displayId, bool &resultValue) override; - ErrCode IsCapacitySupport(int32_t capacity, bool &isSupport) override; protected: void OnStart() override; @@ -103,38 +114,38 @@ private: int32_t Init(); void Initialize(); - std::thread workThreadHandler; /*!< thread handler of the WorkThread */ void RestartSessionIme(std::shared_ptr &session); - std::shared_ptr GetSessionFromMsg(const Message *msg); - int32_t PrepareForOperateKeyboard(std::shared_ptr &session); + int32_t PrepareForOperateKeyboard(const CallerInfo &callerInfo, std::shared_ptr &session); int32_t SwitchByCondition(const Condition &condition, const std::shared_ptr &info); + CallerInfo GetCallerInfo(uint32_t requestId); int32_t GetUserId(int32_t uid); int32_t GetCallingUserId(); - uint64_t GetCallingDisplayId(sptr abilityToken = nullptr); + uint64_t GetCallingDisplayId(int32_t callingPid, sptr abilityToken = nullptr); std::shared_ptr identityChecker_ = nullptr; - int32_t PrepareInput(int32_t userId, InputClientInfo &clientInfo); - void WorkThread(); - int32_t OnUserStarted(const Message *msg); - int32_t OnUserRemoved(const Message *msg); - int32_t OnUserStop(const Message *msg); - int32_t OnHideKeyboardSelf(const Message *msg); + int32_t PrepareInput(const CallerInfo &callerInfo, InputClientInfo &clientInfo); + + // common event callbacks + int32_t OnUserStarted(const EventFwk::CommonEventData &data); + int32_t OnUserRemoved(const EventFwk::CommonEventData &data); + int32_t OnUserStop(const EventFwk::CommonEventData &data); + void OnPackageAdded(const EventFwk::CommonEventData &data); + void OnPackageChanged(const EventFwk::CommonEventData &data); + void OnPackageRemoved(const EventFwk::CommonEventData &data); + void OnScreenUnlock(const EventFwk::CommonEventData &data); + void OnDataShareReady(); + void OnBundleScanFinished(); + bool IsNeedSwitch(int32_t userId, const std::string &bundleName, const std::string &subName); - int32_t CheckEnableAndSwitchPermission(); - int32_t CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo, SwitchTrigger trigger); - bool IsStartInputTypePermitted(int32_t userId); - int32_t OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo, SwitchTrigger trigger); - int32_t StartSwitch(int32_t userId, const SwitchInfo &switchInfo, - const std::shared_ptr &session); - int32_t OnStartInputType(int32_t userId, const SwitchInfo &switchInfo, bool isCheckPermission); - int32_t HandlePackageEvent(const Message *msg); - int32_t OnPackageRemoved(int32_t userId, const std::string &packageName); - void OnScreenUnlock(const Message *msg); + int32_t CheckEnableAndSwitchPermission(const CallerInfo &callerInfo); + int32_t CheckSwitchPermission(const SwitchInfo &switchInfo, SwitchTrigger trigger, const CallerInfo &callerInfo); + bool IsStartInputTypePermitted(const CallerInfo &callerInfo, int32_t userId); + int32_t OnSwitchInputMethod(const CallerInfo &callerInfo, const SwitchInfo &switchInfo, SwitchTrigger trigger); + int32_t StartSwitch(int32_t userId, const SwitchInfo &switchInfo); + int32_t OnStartInputType(const CallerInfo &callerInfo, const SwitchInfo &switchInfo, bool isCheckPermission); int32_t OnDisplayOptionalInputMethod(); - void SubscribeCommonEvent(); - int32_t Switch(int32_t userId, const std::string &bundleName, const std::shared_ptr &info); - int32_t SwitchExtension(int32_t userId, const std::shared_ptr &info); - int32_t SwitchSubType(int32_t userId, const std::shared_ptr &info); + void SubscribeCommonEvents(); + void SubscribeSaListeners(); int32_t SwitchInputType(int32_t userId, const SwitchInfo &switchInfo); void GetValidSubtype(const std::string &subName, const std::shared_ptr &info); ServiceRunningState state_; @@ -146,70 +157,93 @@ private: void HandleUserSwitched(int32_t userId); void HandleWmsStarted(); void HandleMemStarted(); - void HandleDataShareReady(); void HandleOsAccountStarted(); + void HandleMMIStarted(); void HandleFocusChanged(bool isFocused, uint64_t displayId, int32_t pid, int32_t uid); void HandleImeCfgCapsState(); + void HandleDisplayChanged(const Rosen::CallingWindowInfo &callingWindowInfo); void HandlePasteboardStarted(); void StopImeInBackground(); - int32_t InitAccountMonitor(); static std::shared_ptr serviceHandler_; int32_t userId_; - bool stop_ = false; void InitMonitors(); - int32_t InitKeyEventMonitor(); - bool InitWmsMonitor(); void InitSystemLanguageMonitor(); - bool InitMemMgrMonitor(); void InitWmsConnectionMonitor(); void InitFocusChangedMonitor(); void InitWindowDisplayChangedMonitor(); - bool InitPasteboardMonitor(); int32_t SwitchByCombinationKey(uint32_t state); int32_t SwitchMode(); int32_t SwitchLanguage(); int32_t SwitchType(); - int32_t GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo); + int32_t GenerateClientInfo(const CallerInfo &callerInfo, InputClientInfo &clientInfo); void RegisterSecurityModeObserver(); - int32_t CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo); + int32_t CheckInputTypeOption(const CallerInfo &callerInfo, InputClientInfo &inputClientInfo); int32_t IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId); void DealSwitchRequest(); - bool IsCurrentIme(int32_t userId); - int32_t StartInputType(int32_t userId, InputType type); + bool IsCurrentIme(const CallerInfo &callerInfo); + int32_t StartInputType(const CallerInfo &callerInfo, InputType type); // if switch input type need to switch ime, then no need to hide panel first. void NeedHideWhenSwitchInputType(int32_t userId, InputType type, bool &needHide); bool GetDeviceFunctionKeyState(int32_t functionKey, bool &isEnable); bool ModifyImeCfgWithWrongCaps(); - void HandleBundleScanFinished(); - int32_t StartInputInner( - InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo); - int32_t ShowInputInner(sptr client, int32_t requestKeyboardReason = 0); - int32_t ShowCurrentInputInner(); + int32_t ShowInputInner(const CallerInfo &callerInfo, sptr client, int32_t requestKeyboardReason = 0); + int32_t ShowCurrentInputInner(const CallerInfo &callerInfo); std::pair GetCurrentImeInfoForHiSysEvent(int32_t userId); int32_t GetScreenLockIme(int32_t userId, std::string &ime); int32_t GetAlternativeIme(int32_t userId, std::string &ime); static InputType GetSecurityInputType(const InputClientInfo &inputClientInfo); - int32_t StartSecurityIme(int32_t &userId, InputClientInfo &inputClientInfo); + int32_t StartSecurityIme(const CallerInfo &callerInfo, InputClientInfo &inputClientInfo); + int32_t OnStartInput(const CallerInfo &callerInfo, const InputClientInfo &inputClientInfo); + int32_t OnPrepareStartInput(const CallerInfo &callerInfo, const InputClientInfo &info); #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE int64_t GetTickCount(); void ResetDelayUnloadTask(uint32_t code = 0); bool IsImeInUse(); #endif - std::mutex checkMutex_; int32_t EnableIme(int32_t userId, const std::string &bundleName, const std::string &extensionName = "", EnabledStatus status = EnabledStatus::BASIC_MODE); void OnCurrentImeStatusChanged(int32_t userId, const std::string &bundleName, EnabledStatus newStatus); void DataShareCallback(const std::string &key); - bool IsValidBundleName(const std::string &bundleName); + bool IsValidBundleName(const CallerInfo &info, const std::string &bundleName); std::string GetRestoreBundleName(MessageParcel &data); - int32_t RestoreInputmethod(std::string &bundleName); - bool IsOneTimeCodeSwitchSubtype(std::shared_ptr session, const SwitchInfo &switchInfo); + int32_t RestoreInputMethod(const CallerInfo &callerInfo, const std::string &bundleName); + bool IsOneTimeCodeSwitchSubtype(int32_t userId, const SwitchInfo &switchInfo); std::atomic isBundleScanFinished_ = false; std::atomic isScbEnable_ = false; std::mutex switchImeMutex_; std::atomic switchTaskExecuting_ = false; std::atomic targetSwitchCount_ = 0; + + // async tasks + int32_t StartInputTask(const CallerInfo &callerInfo, InputClientInfo clientInfo, StartInputResponse &response); + int32_t HideCurrentInputTask(const CallerInfo &callerInfo); + int32_t SwitchInputMethodTask( + const CallerInfo &callerInfo, const std::string &bundleName, const std::string &subName, uint32_t trigger); + int32_t SetCoreAndAgentTask( + const CallerInfo &callerInfo, const sptr &core, const sptr &agent); + int32_t UnRegisteredProxyImeTask( + const CallerInfo &callerInfo, int32_t type, const sptr &core); + int32_t PanelStatusChangeTask(const CallerInfo &callerInfo, uint32_t status, const ImeWindowInfo &info); + int32_t UpdateListenEventFlagTask( + const CallerInfo &callerInfo, const InputClientInfoInner &clientInfoInner, uint32_t eventFlag); + int32_t SetCallingWindowTask(const CallerInfo &callerInfo, uint32_t windowId, const sptr &client); + int32_t SendPrivateDataTask(const CallerInfo &callerInfo, const Value &value); + int32_t IsCurrentImeByPidTask(const CallerInfo &callerInfo, int32_t pid, bool &resultValue); + int32_t ExitCurrentInputTypeTask(const CallerInfo &callerInfo); + int32_t GetSecurityModeTask(const CallerInfo &callerInfo, int32_t &security); + int32_t ConnectSystemCmdTask( + const CallerInfo &callerInfo, const sptr &channel, sptr &agent); + int32_t GetInputMethodStateTask(const CallerInfo &callerInfo, int32_t &status); + int32_t RegisterProxyImeTask(const CallerInfo &callerInfo, uint64_t displayId, const sptr &core, + const sptr &agent); + int32_t UnregisterProxyImeTask(const CallerInfo &callerInfo, uint64_t displayId); + + // report to hisysevent + void ReportStartInput(const CallerInfo &callerInfo, const InputClientInfo &clientInfo, + const StartInputResponse &response, int32_t ret); + void ReportShowCurrentInput(const CallerInfo &info, uint32_t type, int32_t ret); + void ReportShowInput(const CallerInfo &info, uint32_t type, int32_t ret); }; } // namespace MiscServices } // namespace OHOS diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index 086661701026f40cdb0ef2d466439447cb541a4a..13f5b949ee909c5c555d6de7c8bc18dd3f148857 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -19,16 +19,17 @@ #include #include "block_queue.h" +#include "caller_info.h" #include "client_group.h" #include "event_status_manager.h" #include "iinput_method_core.h" #include "ime_cfg_manager.h" +#include "ime_state_manager.h" #include "input_method_types.h" #include "input_type_manager.h" -#include "inputmethod_message_handler.h" #include "inputmethod_sysevent.h" +#include "service_response_data.h" #include "want.h" -#include "ime_state_manager.h" namespace OHOS { namespace Rosen { @@ -72,24 +73,23 @@ struct ImeData { ImeExtendInfo imeExtendInfo; }; -enum class StartPreDefaultImeStatus : uint32_t { NO_NEED, HAS_STARTED, TO_START }; /**@class PerUserSession * * @brief The class provides session management in input method management service * * This class manages the sessions between input clients and input method engines for each unlocked user. */ -class PerUserSession { +class PerUserSession : public std::enable_shared_from_this { public: explicit PerUserSession(int userId); - PerUserSession(int32_t userId, const std::shared_ptr &eventHandler); ~PerUserSession(); int32_t OnPrepareInput(const InputClientInfo &clientInfo); - int32_t OnStartInput( - const InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo); + int32_t GetBindClientInfo(const InputClientInfo &inputInfo, InputClientInfo &outputInfo); + int32_t OnStartInput(const InputClientInfo &info); int32_t OnReleaseInput(const sptr &client, uint32_t sessionId); - int32_t OnSetCoreAndAgent(const sptr &core, const sptr &agent); + int32_t OnSetCoreAndAgent( + const CallerInfo &callerInfo, const sptr &core, const sptr &agent); int32_t OnHideCurrentInput(uint64_t displayId); int32_t OnShowCurrentInput(uint64_t displayId); int32_t OnShowInput(sptr client, int32_t requestKeyboardReason = 0); @@ -99,7 +99,6 @@ public: void OnSecurityChange(int32_t security); void OnHideSoftKeyBoardSelf(); void NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty); - int32_t SwitchSubtype(const SubProperty &subProperty); int32_t SwitchSubtypeWithoutStartIme(const SubProperty &subProperty); void OnFocused(uint64_t displayId, int32_t pid, int32_t uid); void OnUnfocused(uint64_t displayId, int32_t pid, int32_t uid); @@ -108,17 +107,18 @@ public: int64_t GetInactiveClientPid(uint64_t displayId); int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info, uint64_t displayId); int32_t OnUpdateListenEventFlag(const InputClientInfo &clientInfo); - int32_t OnRegisterProxyIme(const sptr &core, const sptr &agent); - int32_t OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core); int32_t OnRegisterProxyIme( - uint64_t displayId, const sptr &core, const sptr &agent); + const CallerInfo &callerInfo, const sptr &core, const sptr &agent); + int32_t OnRegisterProxyIme(const CallerInfo &callerInfo, uint64_t displayId, const sptr &core, + const sptr &agent); + int32_t OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core); int32_t OnUnregisterProxyIme(uint64_t displayId); int32_t InitConnect(pid_t pid); int32_t StartCurrentIme(bool isStopCurrentIme = false); + int32_t NotifyAfterStartCurrentIme(bool isSubNameUndefined); int32_t StartIme(const std::shared_ptr &ime, bool isStopCurrentIme = false); int32_t StopCurrentIme(); - bool RestartIme(); void AddRestartIme(); bool IsProxyImeEnable(); @@ -131,7 +131,7 @@ public: int32_t RemoveAllCurrentClient(); std::shared_ptr GetReadyImeData(ImeType type); std::shared_ptr GetImeData(ImeType type); - BlockQueue& GetSwitchQueue(); + int32_t PrepareValidIme(ImeType type); bool IsWmsReady(); bool CheckPwdInputPatternConv(InputClientInfo &clientInfo, uint64_t displayId); int32_t RestoreCurrentIme(uint64_t callingDisplayId); @@ -139,8 +139,7 @@ public: std::shared_ptr GetImeNativeCfg(int32_t userId, const std::string &bundleName, const std::string &subName); int32_t OnSetCallingWindow(uint32_t callingWindowId, uint64_t callingDisplayId, sptr client); - int32_t GetInputStartInfo( - uint64_t displayId, bool &isInputStart, uint32_t &callingWndId, int32_t &requestKeyboardReason); + int32_t GetInputStartInfo(uint64_t displayId, InputStartInfo &inputStartInfo); bool IsSaReady(int32_t saId); void TryUnloadSystemAbility(); void OnCallingDisplayIdChanged(const int32_t windowId, const int32_t callingPid, const uint64_t displayId); @@ -154,8 +153,8 @@ public: std::pair GetCurrentInputPattern(); bool IsPreconfiguredDefaultImeSpecified(const InputClientInfo &inputClientInfo); bool AllowSwitchImeByCombinationKey(); - std::pair StartPreconfiguredDefaultIme( - uint64_t callingDisplayId, const ImeExtendInfo &imeExtendInfo = {}, bool isStopCurrentIme = false); + int32_t StartPreconfiguredDefaultIme(uint64_t callingDisplayId, ImeLaunchType &launchType, + const ImeExtendInfo &imeExtendInfo = {}, bool isStopCurrentIme = false); private: struct ResetManager { @@ -177,11 +176,9 @@ private: PerUserSession(const PerUserSession &&); PerUserSession &operator=(const PerUserSession &&); - static constexpr int32_t MAX_WAIT_TIME = 5000; - BlockQueue switchQueue_{ MAX_WAIT_TIME }; - void OnClientDied(sptr remote); - void OnImeDied(const sptr &remote, ImeType type); + void OnImeDied(const sptr &remote, ImeType type, const std::string &bundleName, pid_t pid); + void OnImeDiedInner(const sptr &remote, ImeType type, const std::string &bundleName, pid_t pid); int AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event); int32_t RemoveClient(const sptr &client, const std::shared_ptr &clientGroup, @@ -199,10 +196,11 @@ private: int32_t AddImeData(ImeType type, sptr core, sptr agent, pid_t pid); void RemoveImeData(ImeType type, bool isImeDied); int32_t RemoveIme(const sptr &core, ImeType type); - std::shared_ptr GetValidIme(ImeType type); - int32_t BindClientWithIme(const std::shared_ptr &clientInfo, ImeType type, - bool isBindFromClient = false, uint64_t displayId = DEFAULT_DISPLAY_ID); + bool isBindFromClient = false, uint64_t displayId = DEFAULT_DISPLAY_ID, bool mustStartIme = false); + int32_t OnBindFinished(const std::shared_ptr &clientGroup, const InputClientInfo &clientInfo, ImeType type); + int32_t StartImeInput(ImeType type, const InputClientInfo &clientInfo, bool isBindFromClient); + void UnBindClientWithIme(const std::shared_ptr ¤tClientInfo, const DetachOptions &options); void StopClientInput( const std::shared_ptr &clientInfo, bool isStopInactiveClient = false, bool isAsync = false); @@ -224,8 +222,6 @@ private: bool IsImeBindTypeChanged(ImeType bindImeType); int32_t RequestIme(const std::shared_ptr &data, RequestType type, const IpcExec &exec); - bool WaitForCurrentImeStop(); - void NotifyImeStopFinished(); bool GetCurrentUsingImeId(ImeIdentification &imeId); bool CanStartIme(); int32_t ChangeToDefaultImeIfNeed( @@ -238,24 +234,29 @@ private: int32_t StopReadyCurrentIme(); int32_t HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme); int32_t HandleStartImeTimeout(const std::shared_ptr &ime); + int32_t ForceClearAndStartIme(const std::shared_ptr &imeToStart, bool isWaitStop = true); bool GetInputTypeToStart(std::shared_ptr &imeToStart); - void HandleImeBindTypeChanged(InputClientInfo &newClientInfo, const std::shared_ptr &clientGroup); + void HandleImeBindTypeChanged(InputClientInfo &newClientInfo); int32_t NotifyCallingDisplayChanged(uint64_t displayId); bool GetCallingWindowInfo(const InputClientInfo &clientInfo, Rosen::CallingWindowInfo &callingWindowInfo); int32_t SendPrivateData(const std::unordered_map &privateCommand); void ClearRequestKeyboardReason(std::shared_ptr &clientInfo); std::shared_ptr GetRealCurrentIme(bool needSwitchToPresetImeIfNoCurIme = false); + bool RestartIme(); - std::mutex imeStartLock_; + int32_t StartImeExtAbility(const std::shared_ptr &imeToStart); + int32_t StopImeExtAbility(const std::string &bundleName, const std::string &extName); + + int32_t WaitForImeStart(const std::shared_ptr &ime); + int32_t WaitForImeStop(const std::string &bundleName, const std::string &extName); + int32_t WaitForImeForceStop(const std::string &bundleName, const std::string &extName); - BlockData isImeStarted_{ MAX_IME_START_TIME, false }; + void NotifyImeStartReady(const CallerInfo &info); + void NotifyImeStopFinished(const std::string &bundleName); + + std::mutex imeStartLock_; std::mutex imeDataLock_; std::unordered_map> imeData_; - std::mutex focusedClientLock_; - - std::atomic isSwitching_ = false; - std::mutex imeStopMutex_; - std::condition_variable imeStopCv_; std::mutex restartMutex_; int32_t restartTasks_ = 0; diff --git a/services/include/user_session_manager.h b/services/include/user_session_manager.h index 69fb2b64b4289bc1c5cea75f2c6af9c0245cecf4..a413641c5c003a6e2046869b3107dd76a82ee753 100644 --- a/services/include/user_session_manager.h +++ b/services/include/user_session_manager.h @@ -19,6 +19,15 @@ #include "peruser_session.h" namespace OHOS { namespace MiscServices { +#define GET_USER_SESSION(userId, session, retVal) \ + do { \ + session = UserSessionManager::GetInstance().GetUserSession(userId); \ + if (session == nullptr) { \ + IMSA_HILOGE("%{public}d session is nullptr!", userId); \ + return retVal; \ + } \ + } while (0) + class UserSessionManager { public: static UserSessionManager &GetInstance(); @@ -26,14 +35,12 @@ public: std::shared_ptr GetUserSession(int32_t userId); void AddUserSession(int32_t userId); void RemoveUserSession(int32_t userId); - void SetEventHandler(const std::shared_ptr &eventHandler); private: UserSessionManager() = default; ~UserSessionManager() = default; std::mutex userSessionsLock_; std::unordered_map> userSessions_; - std::shared_ptr eventHandler_; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/src/full_ime_info_manager.cpp b/services/src/full_ime_info_manager.cpp index bd00b0ed135277ce35b07bf56c1c61f11b87e84c..4f01a08b47ce7d553ec716f57a31d709d47170c3 100644 --- a/services/src/full_ime_info_manager.cpp +++ b/services/src/full_ime_info_manager.cpp @@ -18,8 +18,8 @@ #include "common_timer_errors.h" #include "ime_enabled_info_manager.h" #include "ime_info_inquirer.h" -#include "inputmethod_message_handler.h" -#include "message.h" +#include "sa_task_manager.h" + namespace OHOS { namespace MiscServices { constexpr uint32_t TIMER_TASK_INTERNAL = 1 * 60 * 60 * 1000; // updated hourly @@ -39,10 +39,11 @@ FullImeInfoManager::FullImeInfoManager() } timerId_ = timer_.Register( []() { - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_REGULAR_UPDATE_IME_INFO, nullptr); - if (msg != nullptr) { - MessageHandler::Instance()->SendMessage(msg); - } + auto task = [](ServiceResponseData &data, ActionInnerData &) { + FullImeInfoManager::GetInstance().RegularInit(); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_UPDATE_IME_INFO, task)); }, TIMER_TASK_INTERNAL, false); } diff --git a/services/src/im_common_event_manager.cpp b/services/src/im_common_event_manager.cpp index f199d17384306d66fec6bcca591628d8285b37c2..3ab9d19bc698849451fa30a928ca1d88ced23972 100644 --- a/services/src/im_common_event_manager.cpp +++ b/services/src/im_common_event_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -14,338 +14,127 @@ */ #include "im_common_event_manager.h" + +#include + #include "full_ime_info_manager.h" #include "ime_info_inquirer.h" #include "iservice_registry.h" #include "itypes_util.h" -#include "inputmethod_message_handler.h" #include "os_account_adapter.h" +#include "sa_task_manager.h" #include "system_ability_definition.h" namespace OHOS { namespace MiscServices { -using namespace MessageID; -sptr ImCommonEventManager::instance_; -std::mutex ImCommonEventManager::instanceLock_; using namespace OHOS::EventFwk; constexpr const char *COMMON_EVENT_INPUT_PANEL_STATUS_CHANGED = "usual.event.imf.input_panel_status_changed"; constexpr const char *COMMON_EVENT_PARAM_USER_ID = "userId"; constexpr const char *COMMON_EVENT_PARAM_PANEL_STATE = "panelState"; constexpr const char *COMMON_EVENT_PARAM_PANEL_RECT = "panelRect"; -ImCommonEventManager::ImCommonEventManager() -{ -} +const std::unordered_map COMMON_EVENT_TASK_CODE{ + { CommonEventSupport::COMMON_EVENT_USER_SWITCHED, SaTaskCode::ON_USER_STARTED }, + { CommonEventSupport::COMMON_EVENT_USER_REMOVED, SaTaskCode::ON_USER_REMOVED }, + { CommonEventSupport::COMMON_EVENT_USER_STOPPED, SaTaskCode::ON_USER_STOPPED }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, SaTaskCode::ON_PACKAGE_ADDED }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, SaTaskCode::ON_PACKAGE_CHANGED }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, SaTaskCode::ON_PACKAGE_REMOVED }, + { CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, SaTaskCode::ON_BUNDLE_SCAN_FINISHED }, + { CommonEventSupport::COMMON_EVENT_DATA_SHARE_READY, SaTaskCode::ON_DATA_SHARE_READY }, + { CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED, SaTaskCode::ON_BOOT_COMPLETED }, + { CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED, SaTaskCode::ON_SCREEN_UNLOCKED }, +}; +const std::unordered_map SA_EVENT_TASK_CODE{ + { SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN, SaTaskCode::ON_ACCOUNT_SA_STARTED }, + { MEMORY_MANAGER_SA_ID, SaTaskCode::ON_MEM_SA_STARTED }, + { MULTIMODAL_INPUT_SERVICE_ID, SaTaskCode::ON_MMI_SA_STARTED }, + { WINDOW_MANAGER_SERVICE_ID, SaTaskCode::ON_WMS_SA_STARTED }, + { COMMON_EVENT_SERVICE_ID, SaTaskCode::ON_COMMON_EVENT_SA_STARTED }, + { PASTEBOARD_SERVICE_ID, SaTaskCode::ON_PASTEBOARD_SA_STARTED }, +}; -ImCommonEventManager::~ImCommonEventManager() +ImCommonEventManager &ImCommonEventManager::GetInstance() { + static ImCommonEventManager imCommonEventManager; + return imCommonEventManager; } -sptr ImCommonEventManager::GetInstance() +void ImCommonEventManager::RegisterEventHandler(const std::string &eventName, const CommonEventHandler &handler) { - if (instance_ == nullptr) { - std::lock_guard autoLock(instanceLock_); - if (instance_ == nullptr) { - IMSA_HILOGI("instance_ is nullptr."); - instance_ = new (std::nothrow) ImCommonEventManager(); - } - } - return instance_; + std::lock_guard lock(eventMutex_); + eventHandlers_.insert_or_assign(eventName, handler); } -bool ImCommonEventManager::SubscribeEvent() +void ImCommonEventManager::RegisterSaHandler(int32_t saId, const Handler &handler) { - EventFwk::MatchingSkills matchingSkills; - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_SWITCHED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_REMOVED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_DATA_SHARE_READY); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_STOPPED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED); - - EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills); - - std::shared_ptr subscriber = std::make_shared(subscriberInfo); - auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (abilityManager == nullptr) { - IMSA_HILOGE("SubscribeEvent abilityManager is nullptr!"); - return false; - } - sptr listener = new (std::nothrow) SystemAbilityStatusChangeListener([subscriber]() { - bool subscribeResult = EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber); - IMSA_HILOGI("SubscribeCommonEvent ret: %{public}d", subscribeResult); - }); - if (listener == nullptr) { - IMSA_HILOGE("SubscribeEvent listener is nullptr!"); - return false; - } - int32_t ret = abilityManager->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, listener); - if (ret != ERR_OK) { - IMSA_HILOGE("SubscribeEvent SubscribeSystemAbility failed. ret: %{public}d", ret); - return false; - } - return true; + std::lock_guard lock(serviceMutex_); + serviceHandlers_.insert_or_assign(saId, handler); } -bool ImCommonEventManager::SubscribeKeyboardEvent(const Handler &handler) +bool ImCommonEventManager::SubscribeEvents() { - IMSA_HILOGI("ImCommonEventManager::SubscribeKeyboardEvent start."); - auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (abilityManager == nullptr) { - IMSA_HILOGE("SubscribeKeyboardEvent abilityManager is nullptr!"); - return false; - } - sptr listener = new (std::nothrow) SystemAbilityStatusChangeListener([handler]() { - if (handler != nullptr) { - handler(); + EventFwk::MatchingSkills matchingSkills; + { + std::lock_guard lock(eventMutex_); + for (const auto &eventHandler : eventHandlers_) { + matchingSkills.AddEvent(eventHandler.first); } - }); - if (listener == nullptr) { - IMSA_HILOGE("listener is nullptr!"); - return false; } - int32_t ret = abilityManager->SubscribeSystemAbility(MULTIMODAL_INPUT_SERVICE_ID, listener); - if (ret != ERR_OK) { - IMSA_HILOGE("failed to SubscribeSystemAbility, ret: %{public}d!", ret); - return false; - } - return true; -} - -bool ImCommonEventManager::SubscribeWindowManagerService(const Handler &handler) -{ - IMSA_HILOGI("start."); - return SubscribeManagerServiceCommon(handler, WINDOW_MANAGER_SERVICE_ID); -} - -bool ImCommonEventManager::SubscribeMemMgrService(const Handler &handler) -{ - return SubscribeManagerServiceCommon(handler, MEMORY_MANAGER_SA_ID); -} - -bool ImCommonEventManager::SubscribeAccountManagerService(Handler handler) -{ - return SubscribeManagerServiceCommon(handler, SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN); -} - -bool ImCommonEventManager::SubscribePasteboardService(const Handler &handler) -{ - return SubscribeManagerServiceCommon(handler, PASTEBOARD_SERVICE_ID); -} - -bool ImCommonEventManager::UnsubscribeEvent() -{ - return true; -} - -ImCommonEventManager::EventSubscriber::EventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) - : EventFwk::CommonEventSubscriber(subscribeInfo) -{ - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_USER_SWITCHED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->StartUser(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_USER_STOPPED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->StopUser(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_USER_REMOVED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->RemoveUser(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->RemovePackage(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->OnBundleScanFinished(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_DATA_SHARE_READY] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->OnDataShareReady(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->AddPackage(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->ChangePackage(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->HandleBootCompleted(data); - }; - EventManagerFunc_[CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED] = - [] (EventSubscriber *that, const EventFwk::CommonEventData &data) { - return that->OnScreenUnlock(data); - }; -} - -void ImCommonEventManager::EventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data) -{ - auto const &want = data.GetWant(); - std::string action = want.GetAction(); - IMSA_HILOGD("ImCommonEventManager::action: %{public}s!", action.c_str()); - auto iter = EventManagerFunc_.find(action); - if (iter != EventManagerFunc_.end()) { - EventManagerFunc_[action] (this, data); - } -} - -void ImCommonEventManager::EventSubscriber::StopUser(const CommonEventData &data) -{ - HandleUserEvent(MessageID::MSG_ID_USER_STOP, data); -} - -void ImCommonEventManager::EventSubscriber::StartUser(const CommonEventData &data) -{ - HandleUserEvent(MessageID::MSG_ID_USER_START, data); -} - -void ImCommonEventManager::EventSubscriber::RemoveUser(const CommonEventData &data) -{ - HandleUserEvent(MessageID::MSG_ID_USER_REMOVED, data); -} - -void ImCommonEventManager::EventSubscriber::HandleUserEvent(int32_t messageId, const EventFwk::CommonEventData &data) -{ - auto userId = data.GetCode(); - MessageParcel *parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - return; - } - IMSA_HILOGD("userId:%{public}d, messageId:%{public}d", userId, messageId); - parcel->WriteInt32(userId); - Message *msg = new (std::nothrow) Message(messageId, parcel); - if (msg == nullptr) { - delete parcel; - return; + EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills); + auto subscriber = std::make_shared(subscriberInfo); + { + std::lock_guard lock(eventMutex_); + subscriber->SetHandlers(eventHandlers_); } - MessageHandler::Instance()->SendMessage(msg); + bool subscribeResult = EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber); + IMSA_HILOGI("SubscribeCommonEvent ret: %{public}d", subscribeResult); + return subscribeResult; } -void ImCommonEventManager::EventSubscriber::OnBundleScanFinished(const EventFwk::CommonEventData &data) +void ImCommonEventManager::SubscribeSaStatus() { - IMSA_HILOGI("ImCommonEventManager start."); - auto parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - IMSA_HILOGE("failed to create MessageParcel!"); - return; - } - auto msg = new (std::nothrow) Message(MessageID::MSG_ID_BUNDLE_SCAN_FINISHED, parcel); - if (msg == nullptr) { - IMSA_HILOGE("failed to create Message!"); - delete parcel; - return; + for (const auto &iter : serviceHandlers_) { + auto ret = SubscribeManagerServiceCommon(iter.second, iter.first); + IMSA_HILOGI("subscribe sa: %{public}d, result: %{public}d", iter.first, ret); } - MessageHandler::Instance()->SendMessage(msg); } -void ImCommonEventManager::EventSubscriber::OnDataShareReady(const EventFwk::CommonEventData &data) -{ - IMSA_HILOGI("ImCommonEventManager start."); - auto parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - IMSA_HILOGE("failed to create MessageParcel!"); - return; - } - auto msg = new (std::nothrow) Message(MessageID::MSG_ID_DATA_SHARE_READY, parcel); - if (msg == nullptr) { - IMSA_HILOGE("failed to create Message!"); - delete parcel; - return; - } - MessageHandler::Instance()->SendMessage(msg); -} - -void ImCommonEventManager::EventSubscriber::RemovePackage(const CommonEventData &data) -{ - HandlePackageEvent(MessageID::MSG_ID_PACKAGE_REMOVED, data); -} - -void ImCommonEventManager::EventSubscriber::AddPackage(const EventFwk::CommonEventData &data) -{ - HandlePackageEvent(MessageID::MSG_ID_PACKAGE_ADDED, data); -} - -void ImCommonEventManager::EventSubscriber::ChangePackage(const EventFwk::CommonEventData &data) -{ - HandlePackageEvent(MessageID::MSG_ID_PACKAGE_CHANGED, data); -} - -void ImCommonEventManager::EventSubscriber::HandlePackageEvent(int32_t messageId, const EventFwk::CommonEventData &data) +void ImCommonEventManager::EventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data) { auto const &want = data.GetWant(); - auto element = want.GetElement(); - std::string bundleName = element.GetBundleName(); - int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); - if (userId == OsAccountAdapter::INVALID_USER_ID) { - IMSA_HILOGE("invalid user id, messageId:%{public}d", messageId); - return; - } - if (messageId == MessageID::MSG_ID_PACKAGE_REMOVED) { - if (!FullImeInfoManager::GetInstance().Has(userId, bundleName)) { - return; - } - } else { - if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) { - return; - } - } - MessageParcel *parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - IMSA_HILOGE("parcel is nullptr!"); - return; - } - if (!ITypesUtil::Marshal(*parcel, userId, bundleName)) { - IMSA_HILOGE("Failed to write message parcel!"); - delete parcel; + std::string eventName = want.GetAction(); + IMSA_HILOGD("ImCommonEventManager::action: %{public}s!", eventName.c_str()); + auto handler = GetHandler(eventName); + if (handler == nullptr) { return; } - Message *msg = new (std::nothrow) Message(messageId, parcel); - if (msg == nullptr) { - IMSA_HILOGE("failed to create Message!"); - delete parcel; + auto iter = COMMON_EVENT_TASK_CODE.find(eventName); + if (iter == COMMON_EVENT_TASK_CODE.end()) { + IMSA_HILOGE("code of event: %{public}s not found", eventName.c_str()); return; } - MessageHandler::Instance()->SendMessage(msg); + SaTaskCode code = iter->second; + auto task = [handler, data](ServiceResponseData &, ActionInnerData &) -> int32_t { + handler(data); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(code, task)); } -void ImCommonEventManager::EventSubscriber::HandleBootCompleted(const EventFwk::CommonEventData &data) +void ImCommonEventManager::EventSubscriber::SetHandlers(std::unordered_map handlers) { - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_BOOT_COMPLETED, nullptr); - if (msg == nullptr) { - return; - } - MessageHandler::Instance()->SendMessage(msg); + std::lock_guard lock(handlersMutex_); + commonEventHandlers_ = std::move(handlers); } -void ImCommonEventManager::EventSubscriber::OnScreenUnlock(const EventFwk::CommonEventData &data) +CommonEventHandler ImCommonEventManager::EventSubscriber::GetHandler(const std::string &event) { - MessageParcel *parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - IMSA_HILOGE("parcel is nullptr!"); - return; + std::lock_guard lock(handlersMutex_); + auto iter = commonEventHandlers_.find(event); + if (iter == commonEventHandlers_.end()) { + return nullptr; } - auto const &want = data.GetWant(); - int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); - if (!ITypesUtil::Marshal(*parcel, userId)) { - IMSA_HILOGE("Failed to write message parcel!"); - delete parcel; - return; - } - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_SCREEN_UNLOCK, parcel); - if (msg == nullptr) { - IMSA_HILOGE("failed to create Message!"); - delete parcel; - return; - } - MessageHandler::Instance()->SendMessage(msg); + return iter->second; } ImCommonEventManager::SystemAbilityStatusChangeListener::SystemAbilityStatusChangeListener(std::function func) @@ -353,22 +142,29 @@ ImCommonEventManager::SystemAbilityStatusChangeListener::SystemAbilityStatusChan { } -void ImCommonEventManager::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId, - const std::string &deviceId) +void ImCommonEventManager::SystemAbilityStatusChangeListener::OnAddSystemAbility( + int32_t systemAbilityId, const std::string &deviceId) { IMSA_HILOGD("systemAbilityId: %{public}d.", systemAbilityId); - if (systemAbilityId != COMMON_EVENT_SERVICE_ID && systemAbilityId != MULTIMODAL_INPUT_SERVICE_ID && - systemAbilityId != WINDOW_MANAGER_SERVICE_ID && systemAbilityId != SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN && - systemAbilityId != MEMORY_MANAGER_SA_ID && systemAbilityId != PASTEBOARD_SERVICE_ID) { + auto iter = SA_EVENT_TASK_CODE.find(systemAbilityId); + if (iter == SA_EVENT_TASK_CODE.end()) { return; } - if (func_ != nullptr) { - func_(); + if (func_ == nullptr) { + return; } + auto task = [func = func_](ServiceResponseData &, ActionInnerData &innerData) { + if (func != nullptr) { + func(); + } + return ErrorCode::NO_ERROR; + }; + SaTaskCode code = iter->second; + SaTaskManager::GetInstance().PostTask(std::make_shared(code, task)); } -void ImCommonEventManager::SystemAbilityStatusChangeListener::OnRemoveSystemAbility(int32_t systemAbilityId, - const std::string &deviceId) +void ImCommonEventManager::SystemAbilityStatusChangeListener::OnRemoveSystemAbility( + int32_t systemAbilityId, const std::string &deviceId) { } diff --git a/services/src/ime_cfg_manager.cpp b/services/src/ime_cfg_manager.cpp index 2c95ab8c66df3cc799658c4b71a94d4061a33096..c7f5d7f97f2f77a370bcb2116505eb56677b9dac 100644 --- a/services/src/ime_cfg_manager.cpp +++ b/services/src/ime_cfg_manager.cpp @@ -21,7 +21,6 @@ namespace MiscServices { namespace { constexpr const char *IME_CFG_FILE_PATH = "/data/service/el1/public/imf/ime_cfg.json"; } // namespace -std::shared_ptr ImeCfgManager::serviceHandler_ = nullptr; ImeCfgManager &ImeCfgManager::GetInstance() { static ImeCfgManager instance; @@ -48,26 +47,6 @@ void ImeCfgManager::ReadImeCfg() ParseImeCfg(cfg); } -void ImeCfgManager::WriteImeCfg() -{ - auto content = PackageImeCfg(); - if (content.empty()) { - IMSA_HILOGE("failed to Package imeCfg!"); - return; - } - if (serviceHandler_ == nullptr) { - IMSA_HILOGE("serviceHandler_ is nullptr!"); - return; - } - auto task = [content]() { - IMSA_HILOGD("start WriteJsonFile!"); - if (!FileOperator::Write(IME_CFG_FILE_PATH, content, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC)) { - IMSA_HILOGE("failed to WriteJsonFile!"); - } - }; - serviceHandler_->PostTask(task, "WriteImeCfg", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); -} - bool ImeCfgManager::ParseImeCfg(const std::string &content) { IMSA_HILOGD("content: %{public}s", content.c_str()); @@ -113,18 +92,6 @@ void ImeCfgManager::ModifyTempScreenLockImeCfg(int32_t userId, const std::string ImeEnabledInfoManager::GetInstance().SetTmpIme(userId, ime); } -void ImeCfgManager::DeleteImeCfg(int32_t userId) -{ - std::lock_guard lock(imeCfgLock_); - for (auto iter = imeConfigs_.begin(); iter != imeConfigs_.end(); iter++) { - if (iter->userId == userId) { - imeConfigs_.erase(iter); - break; - } - } - WriteImeCfg(); -} - ImePersistInfo ImeCfgManager::GetImeCfg(int32_t userId) { std::lock_guard lock(imeCfgLock_); @@ -148,10 +115,5 @@ bool ImeCfgManager::IsDefaultImeSet(int32_t userId) IMSA_HILOGI("isDefaultImeSet: %{public}d", ret); return ret; } - -void ImeCfgManager::SetEventHandler(const std::shared_ptr &eventHandler) -{ - serviceHandler_ = eventHandler; -} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/ime_lifecycle_manager.cpp b/services/src/ime_lifecycle_manager.cpp index 78742679325857020a80d9590d4d3a21a79f76d7..b7c79d18262bf0776559a888800dc3978ed7a7bd 100644 --- a/services/src/ime_lifecycle_manager.cpp +++ b/services/src/ime_lifecycle_manager.cpp @@ -15,6 +15,7 @@ #include "ime_lifecycle_manager.h" #include "global.h" +#include "sa_task_manager.h" namespace OHOS { namespace MiscServices { @@ -36,19 +37,28 @@ void ImeLifecycleManager::ControlIme(bool shouldApply) std::weak_ptr weakThis = shared_from_this(); eventHandler_->PostTask( [weakThis]() { - auto sharedThis = weakThis.lock(); - if (sharedThis == nullptr) { - IMSA_HILOGE("sharedThis is nullptr."); - return; - } - if (sharedThis->stopImeFunc_ == nullptr) { - IMSA_HILOGE("stopImeFunc_ is nullptr."); - return; - } - IMSA_HILOGD("Stop ime pid %{public}d", sharedThis->pid_); - sharedThis->stopImeFunc_(); + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS_RETURN_VOID(weakThis, sharedThis); + sharedThis->OnStopIme(); }, STOP_IME_TASK_NAME, stopDelayTime_); } + +void ImeLifecycleManager::OnStopIme() +{ + std::weak_ptr weakThis = shared_from_this(); + auto doStop = [weakThis](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + if (sharedThis->stopImeFunc_ == nullptr) { + IMSA_HILOGE("stopImeFunc_ is nullptr."); + return ErrorCode::NO_ERROR; + } + IMSA_HILOGD("Stop ime pid %{public}d", sharedThis->pid_); + sharedThis->stopImeFunc_(); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_IME_LIFE_CYCLE_STOP, doStop)); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/input_control_channel_service_impl.cpp b/services/src/input_control_channel_service_impl.cpp index 49e65de28bb5490d9ff40faec4c868f4185a8a2a..3b5b8c97639ebc85fec049bdbc3967131b39af33 100644 --- a/services/src/input_control_channel_service_impl.cpp +++ b/services/src/input_control_channel_service_impl.cpp @@ -16,9 +16,9 @@ #include "input_control_channel_service_impl.h" #include "ipc_skeleton.h" -#include "inputmethod_message_handler.h" -#include "message_parcel.h" #include "os_account_adapter.h" +#include "sa_task_manager.h" +#include "user_session_manager.h" namespace OHOS { namespace MiscServices { @@ -35,18 +35,15 @@ ErrCode InputControlChannelServiceImpl::HideKeyboardSelf() if (userId == OsAccountAdapter::INVALID_USER_ID) { return ErrorCode::ERROR_EX_ILLEGAL_STATE; } - MessageParcel *parcel = new (std::nothrow) MessageParcel(); - if (parcel == nullptr) { - return ErrorCode::ERROR_NULL_POINTER; - } - parcel->WriteInt32(userId); - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_HIDE_KEYBOARD_SELF, parcel); - if (msg == nullptr) { - delete parcel; - return ErrorCode::ERROR_NULL_POINTER; - } - MessageHandler::Instance()->SendMessage(msg); - return ERR_OK; + auto task = [userId](ServiceResponseData &, ActionInnerData &) { + auto session = UserSessionManager::GetInstance().GetUserSession(userId); + if (session == nullptr) { + return ErrorCode::ERROR_NULL_POINTER; + } + session->OnHideSoftKeyBoardSelf(); + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::HIDE_KEYBOARD_SELF, task)); } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index e3ff0893dfd476bcfc3fe177a2a33849158468c4..1e09e3f328463a986638a76669b0fc835d45aa0c 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -1,4 +1,4 @@ - /* +/* * 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. @@ -32,7 +32,6 @@ #include "itypes_util.h" #include "mem_mgr_client.h" #include "numkey_apps_manager.h" -#include "inputmethod_message_handler.h" #include "os_account_adapter.h" #include "scene_board_judgement.h" #include "system_ability_definition.h" @@ -48,14 +47,18 @@ #include "window_adapter.h" #include "input_method_tools.h" #include "ime_state_manager_factory.h" +#include "requester_manager.h" +#include "sa_task_manager.h" +#include "variant_util.h" namespace OHOS { namespace MiscServices { -using namespace MessageID; using namespace AppExecFwk; +using namespace OHOS::EventFwk; using namespace Security::AccessToken; using namespace std::chrono; using namespace HiviewDFX; +using namespace OHOS::Rosen; constexpr uint32_t FATAL_TIMEOUT = 30; // 30s constexpr int64_t WARNING_TIMEOUT = 5000; // 5s REGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true); @@ -84,12 +87,6 @@ InputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningStat InputMethodSystemAbility::~InputMethodSystemAbility() { - stop_ = true; - Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr); - MessageHandler::Instance()->SendMessage(msg); - if (workThreadHandler.joinable()) { - workThreadHandler.join(); - } } #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE @@ -201,22 +198,23 @@ void InputMethodSystemAbility::OnStart() serviceHandler_->PostTask(callback, INIT_INTERVAL); IMSA_HILOGE("init failed. try again 10s later!"); } + HiviewDFX::XCollie::GetInstance().CancelTimer(id); InitHiTrace(); InputMethodSyncTrace tracer("InputMethodController Attach trace."); InputmethodDump::GetInstance().AddDumpAllMethod([this](int fd) { this->DumpAllMethod(fd); }); - HiviewDFX::XCollie::GetInstance().CancelTimer(id); IMSA_HILOGI("start imsa service success."); return; } -bool InputMethodSystemAbility::IsValidBundleName(const std::string &bundleName) +bool InputMethodSystemAbility::IsValidBundleName(const CallerInfo &info, const std::string &bundleName) { if (bundleName.empty()) { IMSA_HILOGE("bundleName is empty."); return false; } std::vector props; - auto ret = ListInputMethod(InputMethodStatus::ALL, props); + auto ret = ImeInfoInquirer::GetInstance().ListInputMethod( + info.userId, static_cast(InputMethodStatus::ALL), props); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("ListInputMethod failed, ret=%{public}d", ret); return false; @@ -261,33 +259,27 @@ std::string InputMethodSystemAbility::GetRestoreBundleName(MessageParcel &data) return bundleName; } -int32_t InputMethodSystemAbility::RestoreInputmethod(std::string &bundleName) +int32_t InputMethodSystemAbility::RestoreInputMethod(const CallerInfo &callerInfo, const std::string &bundleName) { - Property propertyData; - GetCurrentInputMethod(propertyData); - auto prop = std::make_shared(propertyData); + auto prop = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(callerInfo.userId); + if (prop == nullptr) { + IMSA_HILOGE("failed to GetCurrentInputMethod"); + return ErrorCode::ERROR_IMSA_NULLPTR; + } std::string currentInputMethod = prop->name; if (currentInputMethod == bundleName) { IMSA_HILOGW("currentInputMethod=%{public}s, has been set", currentInputMethod.c_str()); return ErrorCode::NO_ERROR; } - int32_t userId = GetCallingUserId(); - auto result = EnableIme(userId, bundleName); + auto result = EnableIme(callerInfo.userId, bundleName); if (result != ErrorCode::NO_ERROR) { IMSA_HILOGE("EnableIme failed"); return ErrorCode::ERROR_ENABLE_IME; } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("session[ userId=%{public}d ] is nullptr", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, "" }; - switchInfo.timestamp = std::chrono::system_clock::now(); - session->GetSwitchQueue().Push(switchInfo); - auto ret = OnSwitchInputMethod(userId, switchInfo, SwitchTrigger::IMSA); + SwitchInfo switchInfo = { bundleName, "" }; + auto ret = OnSwitchInputMethod(callerInfo, switchInfo, SwitchTrigger::IMSA); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("SwitchInputMethod failed, ret=%{public}d.", ret); return ret; @@ -302,12 +294,17 @@ int32_t InputMethodSystemAbility::OnExtension(const std::string &extension, Mess if (extension == "restore") { (void)data.ReadFileDescriptor(); std::string bundleName = GetRestoreBundleName(data); - if (!IsValidBundleName(bundleName)) { + auto callerInfo = GetCallerInfo(INVALID_SEQ_ID); + if (!IsValidBundleName(callerInfo, bundleName)) { IMSA_HILOGE("bundleName=%{public}s is invalid", bundleName.c_str()); return ErrorCode::ERROR_BAD_PARAMETERS; } - return RestoreInputmethod(bundleName); + auto action = [this, callerInfo, bundleName](ServiceResponseData &, ActionInnerData &) -> int32_t { + return RestoreInputMethod(callerInfo, bundleName); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::ON_EXTENSION, action, callerInfo)); } return 0; } @@ -398,9 +395,7 @@ void InputMethodSystemAbility::OnStop() { IMSA_HILOGI("OnStop start."); ImeStateManager::SetEventHandler(nullptr); - UserSessionManager::GetInstance().SetEventHandler(nullptr); - ImeEnabledInfoManager::GetInstance().SetEventHandler(nullptr); - ImeCfgManager::GetInstance().SetEventHandler(nullptr); + SaTaskManager::GetInstance().Reset(); serviceHandler_ = nullptr; state_ = ServiceRunningState::STATE_NOT_START; Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, INPUT_METHOD_SYSTEM_ABILITY_ID); @@ -416,7 +411,6 @@ void InputMethodSystemAbility::InitServiceHandler() std::shared_ptr runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility"); serviceHandler_ = std::make_shared(runner); ImeStateManager::SetEventHandler(serviceHandler_); - ImeEnabledInfoManager::GetInstance().SetEventHandler(serviceHandler_); IMSA_HILOGI("InitServiceHandler succeeded."); } @@ -427,12 +421,9 @@ void InputMethodSystemAbility::InitServiceHandler() void InputMethodSystemAbility::Initialize() { IMSA_HILOGI("InputMethodSystemAbility::Initialize."); - // init work thread to handle the messages - workThreadHandler = std::thread([this] { this->WorkThread(); }); identityChecker_ = std::make_shared(); userId_ = OsAccountAdapter::MAIN_USER_ID; - UserSessionManager::GetInstance().SetEventHandler(serviceHandler_); - ImeCfgManager::GetInstance().SetEventHandler(serviceHandler_); + SaTaskManager::GetInstance(); UserSessionManager::GetInstance().AddUserSession(userId_); InputMethodSysEvent::GetInstance().SetUserId(userId_); IMSA_HILOGI("start get scene board enable status"); @@ -462,87 +453,50 @@ void InputMethodSystemAbility::RestartSessionIme(std::shared_ptr StopImeInBackground(); } -std::shared_ptr InputMethodSystemAbility::GetSessionFromMsg(const Message *msg) -{ - if (msg == nullptr || msg->msgContent_ == nullptr) { - IMSA_HILOGE("Aborted! Message is nullptr!"); - return nullptr; - } - auto userId = msg->msgContent_->ReadInt32(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return nullptr; - } - return session; -} - -int32_t InputMethodSystemAbility::PrepareForOperateKeyboard(std::shared_ptr &session) +int32_t InputMethodSystemAbility::PrepareForOperateKeyboard( + const CallerInfo &callerInfo, std::shared_ptr &session) { - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - auto userId = GetCallingUserId(); - session = UserSessionManager::GetInstance().GetUserSession(userId); + session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return ErrorCode::ERROR_NULL_POINTER; } - if (!identityChecker_->IsBroker(tokenId)) { - if (!identityChecker_->IsFocused( - IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid(GetCallingDisplayId()))) { + if (!identityChecker_->IsBroker(callerInfo.tokenId)) { + if (!identityChecker_->IsFocused(callerInfo.pid, callerInfo.tokenId, + session->GetCurrentClientPid(GetCallingDisplayId(callerInfo.pid)))) { return ErrorCode::ERROR_CLIENT_NOT_FOCUSED; } } return ErrorCode::NO_ERROR; } -int32_t InputMethodSystemAbility::SwitchByCondition(const Condition &condition, - const std::shared_ptr &info) +int32_t InputMethodSystemAbility::SwitchByCondition(const Condition &condition, const std::shared_ptr &info) { auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition); if (target == nullptr) { IMSA_HILOGE("target is empty!"); return ErrorCode::ERROR_BAD_PARAMETERS; } - SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id }; - auto session = UserSessionManager::GetInstance().GetUserSession(userId_); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId_); - return ErrorCode::ERROR_NULL_POINTER; - } - session->GetSwitchQueue().Push(switchInfo); - return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA); -} - -void InputMethodSystemAbility::SubscribeCommonEvent() -{ - sptr imCommonEventManager = ImCommonEventManager::GetInstance(); - bool isSuccess = imCommonEventManager->SubscribeEvent(); - if (isSuccess) { - IMSA_HILOGI("initialize subscribe service event success."); - return; - } - - IMSA_HILOGE("failed, try again 10s later!"); - auto callback = [this]() { SubscribeCommonEvent(); }; - serviceHandler_->PostTask(callback, INIT_INTERVAL); + SwitchInfo switchInfo = { target->name, target->id }; + return OnSwitchInputMethod({ .userId = userId_ }, switchInfo, SwitchTrigger::IMSA); } -int32_t InputMethodSystemAbility::PrepareInput(int32_t userId, InputClientInfo &clientInfo) +int32_t InputMethodSystemAbility::PrepareInput(const CallerInfo &callerInfo, InputClientInfo &clientInfo) { InputMethodSyncTrace tracer("InputMethodSystemAbility PrepareInput"); - auto ret = GenerateClientInfo(userId, clientInfo); + auto ret = GenerateClientInfo(callerInfo, clientInfo); if (ret != ErrorCode::NO_ERROR) { return ret; } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; } return session->OnPrepareInput(clientInfo); } -int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo) +int32_t InputMethodSystemAbility::GenerateClientInfo(const CallerInfo &callerInfo, InputClientInfo &clientInfo) { if (clientInfo.client == nullptr || clientInfo.channel == nullptr) { IMSA_HILOGE("client or channel is nullptr!"); @@ -553,20 +507,19 @@ int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClient IMSA_HILOGE("failed to new deathRecipient!"); return ErrorCode::ERROR_IMSA_MALLOC_FAILED; } - clientInfo.pid = IPCSkeleton::GetCallingPid(); - clientInfo.uid = IPCSkeleton::GetCallingUid(); - clientInfo.displayId = GetCallingDisplayId(clientInfo.config.abilityToken); - clientInfo.userID = userId; + clientInfo.pid = callerInfo.pid; + clientInfo.uid = callerInfo.uid; + clientInfo.displayId = GetCallingDisplayId(callerInfo.pid, clientInfo.config.abilityToken); + clientInfo.userID = callerInfo.userId; clientInfo.deathRecipient = deathRecipient; - auto tokenId = IPCSkeleton::GetCallingTokenID(); - if (identityChecker_->IsFocusedUIExtension(tokenId)) { - clientInfo.uiExtensionTokenId = tokenId; + if (identityChecker_->IsFocusedUIExtension(callerInfo.tokenId)) { + clientInfo.uiExtensionTokenId = callerInfo.tokenId; } auto callingDisplayId = identityChecker_->GetDisplayIdByWindowId(clientInfo.config.windowId); - clientInfo.config.privateCommand.insert_or_assign("displayId", - PrivateDataValue(static_cast(callingDisplayId))); - clientInfo.name = ImfHiSysEventUtil::GetAppName(tokenId); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + clientInfo.config.privateCommand.insert_or_assign( + "displayId", PrivateDataValue(static_cast(callingDisplayId))); + clientInfo.name = ImfHiSysEventUtil::GetAppName(callerInfo.tokenId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session != nullptr) { auto callingWindowInfo = session->GetCallingWindowInfo(clientInfo); clientInfo.config.inputAttribute.windowId = callingWindowInfo.windowId; @@ -579,101 +532,152 @@ int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClient return ErrorCode::NO_ERROR; } -ErrCode InputMethodSystemAbility::ReleaseInput(const sptr& client, uint32_t sessionId) +ErrCode InputMethodSystemAbility::ReleaseInput(uint32_t requestId, const sptr &client, uint32_t sessionId) { - if (client == nullptr) { - IMSA_HILOGE("client is nullptr!"); - return ErrorCode::ERROR_CLIENT_NULL_POINTER; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnReleaseInput(client, sessionId); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + auto action = [userId = callerInfo.userId, sessionId, client](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_NULL_POINTER); + return session->OnReleaseInput(client, sessionId); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::RELEASE_INPUT, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::StartInput( - const InputClientInfoInner &inputClientInfoInner, sptr &agent, int64_t &pid, std::string &bundleName) +ErrCode InputMethodSystemAbility::RegisterImaResponseChannel(const sptr &channel) { - InputClientInfo inputClientInfo = - InputMethodTools::GetInstance().InnerToInputClientInfo(inputClientInfoInner); - agent = nullptr; - pid = 0; - bundleName = ""; - std::pair imeInfo{ pid, bundleName }; - auto ret = StartInputInner(const_cast(inputClientInfo), agent, imeInfo); - IMSA_HILOGD("HiSysEvent report start!"); - auto evenInfo = HiSysOriginalInfo::Builder() - .SetPeerName(ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID())) - .SetPeerPid(IPCSkeleton::GetCallingPid()) - .SetPeerUserId(GetCallingUserId()) - .SetClientType(inputClientInfo.type) - .SetInputPattern(inputClientInfo.attribute.inputPattern) - .SetIsShowKeyboard(inputClientInfo.isShowKeyboard) - .SetImeName(imeInfo.second) - .SetErrCode(ret) - .Build(); - ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_ATTACH, *evenInfo); - IMSA_HILOGE("HiSysEvent report end!"); - return ret; + return RequesterManager::GetInstance().AddImaChannel(IPCSkeleton::GetCallingPid(), channel); } -int32_t InputMethodSystemAbility::StartInputInner( - InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo) +ErrCode InputMethodSystemAbility::RegisterImcResponseChannel(const sptr &channel) { - auto userId = GetCallingUserId(); - imeInfo = GetCurrentImeInfoForHiSysEvent(userId); - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - if (!identityChecker_->IsBroker(tokenId) && !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, - IdentityChecker::INVALID_PID, true, inputClientInfo.config.abilityToken)) { + return RequesterManager::GetInstance().AddImcChannel(IPCSkeleton::GetCallingPid(), channel); +} + +ErrCode InputMethodSystemAbility::StartInput(uint32_t requestId, const InputClientInfoInner &inputClientInfoInner) +{ + CallerInfo callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + auto clientInfo = InputMethodTools::GetInstance().InnerToInputClientInfo(inputClientInfoInner); + // 1 - generate StartInput task + auto action = [this, callerInfo, clientInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + return StartInputTask(callerInfo, clientInfo); + }; + // 2 - generate HiSysEvent reporter + ReportFunc reporter = [this, callerInfo, clientInfo](int32_t ret, const ServiceResponseData &data) { + // get response data + StartInputResponse response; + GET_VARIANT_DATA_VALUE_RETURN_VOID(data, response); + ReportStartInput(callerInfo, clientInfo, response, ret); + }; + auto task = std::make_shared(SaTaskCode::START_INPUT, action, callerInfo, requester->imcResponseChannel); + task->SetHiSysReporter(reporter); + return SaTaskManager::GetInstance().PostTask(task); +} + +int32_t InputMethodSystemAbility::StartInputTask(const CallerInfo &callerInfo, InputClientInfo clientInfo) +{ + SaActionFunc setInfo = [callerInfo, this](ServiceResponseData &data, ActionInnerData &) { + auto imeInfo = GetCurrentImeInfoForHiSysEvent(callerInfo.userId); + StartInputResponse response; + response.Set(nullptr, imeInfo.first, imeInfo.second); + data = response; + return ErrorCode::NO_ERROR; + }; + SaActionFunc prepareStartInput = [callerInfo, clientInfo, this]( + ServiceResponseData &, ActionInnerData &) -> int32_t { + return OnPrepareStartInput(callerInfo, clientInfo); + }; + SaActionFunc doStartInput = [callerInfo, this](ServiceResponseData &, ActionInnerData &innerData) -> int32_t { + InputClientInfo info; + GET_VARIANT_DATA_VALUE(innerData, info, ErrorCode::ERROR_IMSA_NULLPTR); + return OnStartInput(callerInfo, info); + }; + return SaTaskManager::GetInstance().Pend(setInfo, prepareStartInput, doStartInput); +} + +int32_t InputMethodSystemAbility::OnPrepareStartInput(const CallerInfo &callerInfo, const InputClientInfo &info) +{ + if (!identityChecker_->IsBroker(callerInfo.tokenId) && !identityChecker_->IsFocused( + callerInfo.pid, callerInfo.tokenId, IdentityChecker::INVALID_PID, true, info.config.abilityToken)) { return ErrorCode::ERROR_CLIENT_NOT_FOCUSED; } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; - } - auto displayId = GetCallingDisplayId(); - if (session->GetCurrentClientPid(displayId) != IPCSkeleton::GetCallingPid() - && session->GetInactiveClientPid(displayId) != IPCSkeleton::GetCallingPid()) { - // notify inputStart when caller pid different from both current client and inactive client - inputClientInfo.isNotifyInputStart = true; - } - if (session->CheckPwdInputPatternConv(inputClientInfo, displayId)) { - inputClientInfo.needHide = true; - inputClientInfo.isNotifyInputStart = true; - } - if (session->IsDefaultDisplayGroup(displayId) && !session->IsProxyImeEnable()) { - auto ret = CheckInputTypeOption(userId, inputClientInfo); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("%{public}d failed to CheckInputTypeOption!", userId); - return ret; + + // 1 - generate preparation action for Client + auto displayId = GetCallingDisplayId(callerInfo.pid); + auto prepareClient = [callerInfo, info, displayId](ServiceResponseData &, ActionInnerData &innerData) { + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + InputClientInfo clientInfo = info; + if (session->GetCurrentClientPid(displayId) != callerInfo.pid + && session->GetInactiveClientPid(displayId) != callerInfo.pid) { + // notify inputStart when caller pid different from both current client and inactive client + clientInfo.isNotifyInputStart = true; } - } - inputClientInfo.config.inputAttribute.bundleName = identityChecker_->GetBundleNameByToken(tokenId); - int32_t ret = PrepareInput(userId, inputClientInfo); + if (session->CheckPwdInputPatternConv(clientInfo, displayId)) { + clientInfo.needHide = true; + clientInfo.isNotifyInputStart = true; + } + // pass clientInfo to the next action + innerData = clientInfo; + return ErrorCode::NO_ERROR; + }; + + // 2 - generate preparation action for InputMethod + auto prepareIme = [callerInfo, displayId, this](ServiceResponseData &, ActionInnerData &innerData) -> int32_t { + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + // get clientInfo from the previous action + InputClientInfo info; + GET_VARIANT_DATA_VALUE(innerData, info, ErrorCode::ERROR_IMSA_NULLPTR); + if (session->IsDefaultDisplayGroup(displayId) && !session->IsProxyImeEnable()) { + return CheckInputTypeOption(callerInfo, info); + } + innerData = info; + return ErrorCode::NO_ERROR; + }; + auto onFail = [callerInfo](int32_t) { IMSA_HILOGE("%{public}d CheckInputTypeOption failed", callerInfo.userId); }; + auto prepareImeAction = std::make_unique(prepareIme, nullptr, onFail); + + // pend the above two actions + return SaTaskManager::GetInstance().Pend(prepareClient, std::move(prepareImeAction)); +} + +int32_t InputMethodSystemAbility::OnStartInput(const CallerInfo &callerInfo, const InputClientInfo &inputClientInfo) +{ + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + + InputClientInfo info = inputClientInfo; + info.config.inputAttribute.bundleName = identityChecker_->GetBundleNameByToken(callerInfo.tokenId); + + int32_t ret = PrepareInput(callerInfo, info); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to PrepareInput!"); return ret; } session->SetInputType(); - return session->OnStartInput(inputClientInfo, agent, imeInfo); + return session->OnStartInput(info); } -int32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo) +int32_t InputMethodSystemAbility::CheckInputTypeOption(const CallerInfo &callerInfo, InputClientInfo &inputClientInfo) { IMSA_HILOGI("SecurityImeFlag: %{public}d, IsSameTextInput: %{public}d, IsStarted: %{public}d.", - inputClientInfo.config.inputAttribute.IsSecurityImeFlag(), - !inputClientInfo.isNotifyInputStart, + inputClientInfo.config.inputAttribute.IsSecurityImeFlag(), !inputClientInfo.isNotifyInputStart, InputTypeManager::GetInstance().IsStarted()); if (inputClientInfo.config.inputAttribute.IsSecurityImeFlag()) { - return StartSecurityIme(userId, inputClientInfo); + return StartSecurityIme(callerInfo, inputClientInfo); } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; } if (!inputClientInfo.isNotifyInputStart && InputTypeManager::GetInstance().IsStarted()) { @@ -687,31 +691,42 @@ int32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClie #ifdef IMF_SCREENLOCK_MGR_ENABLE if (ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked()) { std::string ime; - if (GetScreenLockIme(userId, ime) != ErrorCode::NO_ERROR) { + if (GetScreenLockIme(callerInfo.userId, ime) != ErrorCode::NO_ERROR) { IMSA_HILOGE("not ime screenlocked"); return ErrorCode::ERROR_IMSA_IME_TO_START_NULLPTR; } - ImeCfgManager::GetInstance().ModifyTempScreenLockImeCfg(userId, ime); + ImeCfgManager::GetInstance().ModifyTempScreenLockImeCfg(callerInfo.userId, ime); return session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); } #endif if (session->IsPreconfiguredDefaultImeSpecified(inputClientInfo)) { - auto [ret, status] = session->StartPreconfiguredDefaultIme(DEFAULT_DISPLAY_ID); - return ret; + ImeLaunchType type; + return session->StartPreconfiguredDefaultIme(DEFAULT_DISPLAY_ID, type); } return session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); } -ErrCode InputMethodSystemAbility::IsDefaultImeScreen(uint64_t displayId, bool &resultValue) +ErrCode InputMethodSystemAbility::IsDefaultImeScreen(uint32_t requestId, uint64_t displayId) { - resultValue = ImeInfoInquirer::GetInstance().IsDefaultImeScreen(displayId); - return ErrorCode::NO_ERROR; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [displayId](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = ImeInfoInquirer::GetInstance().IsDefaultImeScreen(displayId); + data = resultValue; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_DEFAULT_IME_SCREEN, action, callerInfo, requester->imaResponseChannel)); } -int32_t InputMethodSystemAbility::ShowInputInner(sptr client, int32_t requestKeyboardReason) +int32_t InputMethodSystemAbility::ShowInputInner( + const CallerInfo &callerInfo, sptr client, int32_t requestKeyboardReason) { std::shared_ptr session = nullptr; - auto result = PrepareForOperateKeyboard(session); + auto result = PrepareForOperateKeyboard(callerInfo, session); if (result != ErrorCode::NO_ERROR) { return result; } @@ -722,326 +737,408 @@ int32_t InputMethodSystemAbility::ShowInputInner(sptr client, int3 return session->OnShowInput(client, requestKeyboardReason); } -ErrCode InputMethodSystemAbility::HideInput(const sptr& client) +ErrCode InputMethodSystemAbility::HideInput(uint32_t requestId, const sptr &client) { - std::shared_ptr session = nullptr; - auto result = PrepareForOperateKeyboard(session); - if (result != ErrorCode::NO_ERROR) { - return result; - } - if (client == nullptr) { - IMSA_HILOGE("client is nullptr!"); - return ErrorCode::ERROR_CLIENT_NULL_POINTER; - } - return session->OnHideInput(client); -} + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); -ErrCode InputMethodSystemAbility::StopInputSession() -{ - std::shared_ptr session = nullptr; - auto result = PrepareForOperateKeyboard(session); - if (result != ErrorCode::NO_ERROR) { - return result; - } - return session->OnHideCurrentInput(GetCallingDisplayId()); + SaActionFunc action = [this, callerInfo, client](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + auto ret = PrepareForOperateKeyboard(callerInfo, session); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + if (client == nullptr) { + IMSA_HILOGE("client is nullptr!"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + return session->OnHideInput(client); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::HIDE_INPUT, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::RequestShowInput() +ErrCode InputMethodSystemAbility::StopInputSession(uint32_t requestId) { - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) && - !identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { - return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; - } - return session->OnRequestShowInput(GetCallingDisplayId()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + auto result = PrepareForOperateKeyboard(callerInfo, session); + if (result != ErrorCode::NO_ERROR) { + return result; + } + return session->OnHideCurrentInput(GetCallingDisplayId(callerInfo.pid)); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::STOP_INPUT_SESSION, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::RequestHideInput(bool isFocusTriggered) +ErrCode InputMethodSystemAbility::RequestShowInput(uint32_t requestId) { - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - auto pid = IPCSkeleton::GetCallingPid(); - if (isFocusTriggered) { - if (!identityChecker_->IsFocused(pid, tokenId)) { + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + if (!identityChecker_->IsFocused(callerInfo.pid, callerInfo.tokenId) + && !identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } - } else { - if (!identityChecker_->IsFocused(pid, tokenId) && - !identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { - return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + return session->OnRequestShowInput(GetCallingDisplayId(callerInfo.pid)); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::REQUEST_SHOW_INPUT, action, callerInfo, requester->imcResponseChannel)); +} + +ErrCode InputMethodSystemAbility::RequestHideInput(uint32_t requestId, bool isFocusTriggered) +{ + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, isFocusTriggered](ServiceResponseData &, ActionInnerData &) -> int32_t { + if (isFocusTriggered) { + if (!identityChecker_->IsFocused(callerInfo.pid, callerInfo.tokenId)) { + return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; + } + } else { + if (!identityChecker_->IsFocused(callerInfo.pid, callerInfo.tokenId) + && !identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { + return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; + } } - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnRequestHideInput(pid, GetCallingDisplayId()); + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_NULL_POINTER); + return session->OnRequestHideInput(callerInfo.pid, GetCallingDisplayId(callerInfo.pid)); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::REQUEST_HIDE_INPUT, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::SetCoreAndAgent(const sptr &core, const sptr &agent) +ErrCode InputMethodSystemAbility::SetCoreAndAgent( + uint32_t requestId, const sptr &core, const sptr &agent) +{ + CallerInfo callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, core, agent, callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + return SetCoreAndAgentTask(callerInfo, core, agent); + }; + auto task = + std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, action, callerInfo, requester->imaResponseChannel); + return SaTaskManager::GetInstance().PostTask(task); +} + +int32_t InputMethodSystemAbility::SetCoreAndAgentTask( + const CallerInfo &callerInfo, const sptr &core, const sptr &agent) { IMSA_HILOGD("InputMethodSystemAbility start."); - auto userId = GetCallingUserId(); + auto userId = callerInfo.userId; auto session = UserSessionManager::GetInstance().GetUserSession(userId); if (session == nullptr) { IMSA_HILOGE("%{public}d session is nullptr!", userId); return ErrorCode::ERROR_NULL_POINTER; } - if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - return session->OnRegisterProxyIme(core, agent); + if (identityChecker_->IsNativeSa(callerInfo.tokenId)) { + return session->OnRegisterProxyIme(callerInfo, core, agent); } if (!IsCurrentIme(userId)) { IMSA_HILOGE("not current ime, userId:%{public}d", userId); return ErrorCode::ERROR_NOT_CURRENT_IME; } - return session->OnSetCoreAndAgent(core, agent); + return session->OnSetCoreAndAgent(callerInfo, core, agent); } -int32_t InputMethodSystemAbility::RegisterProxyIme( - uint64_t displayId, const sptr &core, const sptr &agent) +ErrCode InputMethodSystemAbility::RegisterProxyIme( + uint32_t requestId, uint64_t displayId, const sptr &core, const sptr &agent) { - if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) { - IMSA_HILOGE("current device does not support app agent"); - return ErrorCode::ERROR_DEVICE_UNSUPPORTED; - } - if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) { - IMSA_HILOGE("not agent sa"); - return ErrorCode::ERROR_NOT_AI_APP_IME; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnRegisterProxyIme(displayId, core, agent); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + auto action = [this, callerInfo, displayId, core, agent](ServiceResponseData &, ActionInnerData &) -> int32_t { + return RegisterProxyImeTask(callerInfo, displayId, core, agent); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::REGISTER_PROXY_IME, action, callerInfo, requester->imaResponseChannel)); } -int32_t InputMethodSystemAbility::UnregisterProxyIme(uint64_t displayId) +ErrCode InputMethodSystemAbility::UnregisterProxyIme(uint32_t requestId, uint64_t displayId) { - if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) { - IMSA_HILOGE("current device does not support app agent"); - return ErrorCode::ERROR_DEVICE_UNSUPPORTED; - } - if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) { - IMSA_HILOGE("not agent sa"); - return ErrorCode::ERROR_NOT_AI_APP_IME; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnUnregisterProxyIme(displayId); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, displayId](ServiceResponseData &, ActionInnerData &) -> int32_t { + return UnregisterProxyImeTask(callerInfo, displayId); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::UNREGISTER_PROXY_IME, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::InitConnect() +ErrCode InputMethodSystemAbility::InitConnect(uint32_t requestId) { - IMSA_HILOGD("InputMethodSystemAbility init connect."); - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - if (!IsCurrentIme(userId)) { - return ErrorCode::ERROR_NOT_CURRENT_IME; - } - return session->InitConnect(IPCSkeleton::GetCallingPid()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGD("InputMethodSystemAbility init connect."); + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_NULL_POINTER); + if (!IsCurrentIme(callerInfo)) { + return ErrorCode::ERROR_NOT_CURRENT_IME; + } + return session->InitConnect(callerInfo.pid); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::INIT_CONNECT, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::HideCurrentInput() +ErrCode InputMethodSystemAbility::HideCurrentInput(uint32_t requestId) { - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - if (identityChecker_->IsBroker(tokenId)) { - return session->OnHideCurrentInput(GetCallingDisplayId()); - } - if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { - return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; - } - return session->OnHideCurrentInput(GetCallingDisplayId()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return HideCurrentInputTask(callerInfo); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::HIDE_CURRENT_INPUT, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::ShowCurrentInputInner() +int32_t InputMethodSystemAbility::ShowCurrentInputInner(const CallerInfo &callerInfo) { - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; } - if (identityChecker_->IsBroker(tokenId)) { - return session->OnShowCurrentInput(GetCallingDisplayId()); + if (identityChecker_->IsBroker(callerInfo.tokenId)) { + return session->OnShowCurrentInput(GetCallingDisplayId(callerInfo.pid)); } - if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { + if (!identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } - return session->OnShowCurrentInput(GetCallingDisplayId()); + return session->OnShowCurrentInput(GetCallingDisplayId(callerInfo.pid)); } -ErrCode InputMethodSystemAbility::PanelStatusChange(uint32_t status, const ImeWindowInfo &info) +ErrCode InputMethodSystemAbility::PanelStatusChange(uint32_t requestId, uint32_t status, const ImeWindowInfo &info) { - auto userId = GetCallingUserId(); - if (!IsCurrentIme(userId)) { - IMSA_HILOGE("not current ime!"); - return ErrorCode::ERROR_NOT_CURRENT_IME; - } - auto commonEventManager = ImCommonEventManager::GetInstance(); - if (commonEventManager != nullptr) { - auto ret = ImCommonEventManager::GetInstance()->PublishPanelStatusChangeEvent( - userId, static_cast(status), info); - IMSA_HILOGD("public panel status change event: %{public}d", ret); - } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnPanelStatusChange(static_cast(status), info, GetCallingDisplayId()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, status, info, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return PanelStatusChangeTask(callerInfo, status, info); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::PANEL_STATUS_CHANGE, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::UpdateListenEventFlag(const InputClientInfoInner &clientInfoInner, uint32_t eventFlag) +ErrCode InputMethodSystemAbility::UpdateListenEventFlag( + uint32_t requestId, const InputClientInfoInner &clientInfoInner, uint32_t eventFlag) { - InputClientInfo clientInfo = InputMethodTools::GetInstance().InnerToInputClientInfo(clientInfoInner); - IMSA_HILOGD("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag); - if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag) || - EventStatusManager::IsInputStatusChangedOn(eventFlag)) { - if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) && - !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - IMSA_HILOGE("not system application!"); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, clientInfoInner, eventFlag, this]( + ServiceResponseData &, ActionInnerData &) -> int32_t { + return UpdateListenEventFlagTask(callerInfo, clientInfoInner, eventFlag); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, action, callerInfo, requester->imcResponseChannel)); +} + +ErrCode InputMethodSystemAbility::SetCallingWindow( + uint32_t requestId, uint32_t windowId, const sptr &client) +{ + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, windowId, client, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return SetCallingWindowTask(callerInfo, windowId, client); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::SET_CALLING_WINDOW, action, callerInfo, requester->imcResponseChannel)); +} + +ErrCode InputMethodSystemAbility::GetInputStartInfo(uint32_t requestId) +{ + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &data, ActionInnerData &) -> int32_t { + if (!identityChecker_->IsNativeSa(callerInfo.tokenId)) { + IMSA_HILOGE("not native sa!"); return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; } - } - auto userId = GetCallingUserId(); - auto ret = GenerateClientInfo(userId, const_cast(clientInfo)); - if (ret != ErrorCode::NO_ERROR) { + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, false); + InputStartInfo info; + auto ret = session->GetInputStartInfo(GetCallingDisplayId(callerInfo.pid), info); + data = info; return ret; - } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnUpdateListenEventFlag(clientInfo); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::GET_INPUT_START_INFO, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::SetCallingWindow(uint32_t windowId, const sptr& client) +ErrCode InputMethodSystemAbility::IsCurrentIme(uint32_t requestId) { - IMSA_HILOGD("IMF SA setCallingWindow enter"); - if (identityChecker_ == nullptr) { - return ErrorCode::ERROR_NULL_POINTER; - } - AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID(); - if (!identityChecker_->IsBroker(tokenId) && - !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) { - return ErrorCode::ERROR_CLIENT_NOT_FOCUSED; - } - auto callingUserId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", callingUserId); - return ErrorCode::ERROR_NULL_POINTER; - } - auto callingDisplayId = identityChecker_->GetDisplayIdByWindowId(windowId); - return session->OnSetCallingWindow(windowId, callingDisplayId, client); -} + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); -ErrCode InputMethodSystemAbility::GetInputStartInfo(bool& isInputStart, - uint32_t& callingWndId, int32_t &requestKeyboardReason) -{ - if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - IMSA_HILOGE("not native sa!"); - return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; - } - auto callingUserId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", callingUserId); - return false; - } - return session->GetInputStartInfo(GetCallingDisplayId(), isInputStart, callingWndId, requestKeyboardReason); + SaActionFunc action = [this, callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = IsCurrentIme(callerInfo); + data = resultValue; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_CURRENT_IME, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::IsCurrentIme(bool& resultValue) +ErrCode InputMethodSystemAbility::IsInputTypeSupported(uint32_t requestId, int32_t type) { - resultValue = IsCurrentIme(GetCallingUserId()); - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, type](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = InputTypeManager::GetInstance().IsSupported(static_cast(type)); + data = resultValue; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::IS_INPUT_TYPE_SUPPORTED, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::IsInputTypeSupported(int32_t type, bool &resultValue) +ErrCode InputMethodSystemAbility::StartInputType(uint32_t requestId, int32_t type) { - resultValue = InputTypeManager::GetInstance().IsSupported(static_cast(type)); - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, type](ServiceResponseData &, ActionInnerData &) -> int32_t { + return StartInputType(callerInfo, static_cast(type)); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::START_INPUT_TYPE, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::StartInputType(int32_t type) +ErrCode InputMethodSystemAbility::ExitCurrentInputType(uint32_t requestId) { - return StartInputType(GetCallingUserId(), static_cast(type)); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + return ExitCurrentInputTypeTask(callerInfo); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::EXIT_CURRENT_INPUT_TYPE, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::ExitCurrentInputType() +ErrCode InputMethodSystemAbility::IsDefaultIme(uint32_t requestId) { - auto userId = GetCallingUserId(); - auto ret = IsDefaultImeFromTokenId(userId, IPCSkeleton::GetCallingTokenID()); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("not default ime!"); - return ErrorCode::ERROR_NOT_DEFAULT_IME; - } - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - if (session->CheckSecurityMode()) { - return StartInputType(userId, InputType::SECURITY_INPUT); - } - auto typeIme = InputTypeManager::GetInstance().GetCurrentIme(); - auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId); - if (cfgIme->bundleName == typeIme.bundleName) { - return session->RestoreCurrentImeSubType(DEFAULT_DISPLAY_ID); - } - return session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + auto ret = IsDefaultImeFromTokenId(callerInfo.userId, callerInfo.tokenId); + data = ret == ErrorCode::NO_ERROR; + return ret; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_DEFAULT_IME, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::IsDefaultIme() +ErrCode InputMethodSystemAbility::IsSystemApp(uint32_t requestId) { - return IsDefaultImeFromTokenId(GetCallingUserId(), IPCSkeleton::GetCallingTokenID()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()); + data = resultValue; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_SYSTEM_APP, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::IsSystemApp(bool& resultValue) +ErrCode InputMethodSystemAbility::IsSystemImeApp(uint32_t requestId) { - resultValue = identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()); - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()); + data = resultValue; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_SYSTEM_IME_APP, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::IsCapacitySupport(int32_t capacity, bool &isSupport) +ErrCode InputMethodSystemAbility::IsCapacitySupport(uint32_t requestId, int32_t capacity) { - IMSA_HILOGI("capacity:%{public}d", capacity); - if (capacity != static_cast(CapacityType::IMMERSIVE_EFFECT)) { - IMSA_HILOGE("capacity is invalid!"); - return ErrorCode::ERROR_PARAMETER_CHECK_FAILED; - } + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); - const auto &supportedCapacityList = ImeInfoInquirer::GetInstance().GetSystemConfig().supportedCapacityList; - if (supportedCapacityList.find("immersive_effect") != supportedCapacityList.end()) { - isSupport = true; - } - return ERR_OK; + SaActionFunc action = [callerInfo, capacity](ServiceResponseData &data, ActionInnerData &) -> int32_t { + IMSA_HILOGI("capacity:%{public}d", capacity); + if (capacity != static_cast(CapacityType::IMMERSIVE_EFFECT)) { + IMSA_HILOGE("capacity is invalid!"); + return ErrorCode::ERROR_PARAMETER_CHECK_FAILED; + } + bool isSupport = false; + const auto &supportedCapacityList = ImeInfoInquirer::GetInstance().GetSystemConfig().supportedCapacityList; + if (supportedCapacityList.find("immersive_effect") != supportedCapacityList.end()) { + isSupport = true; + } + data = isSupport; + return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_DEFAULT_IME, action, callerInfo, requester->imaResponseChannel)); } int32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId) @@ -1058,56 +1155,88 @@ int32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32 return ErrorCode::NO_ERROR; } -ErrCode InputMethodSystemAbility::IsCurrentImeByPid(int32_t pid, bool& resultValue) +ErrCode InputMethodSystemAbility::IsCurrentImeByPid(uint32_t requestId, int32_t pid) { - if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) && - !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - IMSA_HILOGE("not system application or system ability!"); - resultValue = false; - return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - resultValue = false; - return ErrorCode::ERROR_NULL_POINTER; - } - resultValue = session->IsCurrentImeByPid(pid); - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, pid](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = false; + int32_t ret = IsCurrentImeByPidTask(callerInfo, pid, resultValue); + data = resultValue; + return ret; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_CURRENT_IME_BY_PID, action, callerInfo, requester->imcResponseChannel)); } -int32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown) +int32_t InputMethodSystemAbility::IsPanelShown(uint32_t requestId, const PanelInfo &panelInfo) { - if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) { - IMSA_HILOGE("not system application!"); - return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->IsPanelShown(panelInfo, isShown); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, panelInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + if (!identityChecker_->IsSystemApp(callerInfo.fullTokenId)) { + IMSA_HILOGE("not system application!"); + return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; + } + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_NULL_POINTER); + bool isShown = false; + int32_t ret = session->IsPanelShown(panelInfo, isShown); + data = isShown; + return ret; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_PANEL_SHOWN, action, callerInfo, requester->imcResponseChannel)); } -int32_t InputMethodSystemAbility::DisplayOptionalInputMethod() +int32_t InputMethodSystemAbility::DisplayOptionalInputMethod(uint32_t requestId) { - IMSA_HILOGD("InputMethodSystemAbility start."); - return OnDisplayOptionalInputMethod(); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGD("DisplayOptionalInputMethod start."); + return OnDisplayOptionalInputMethod(); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::DISPLAY_OPTIONAL_INPUT_METHOD, action, callerInfo, requester->imcResponseChannel)); +} + +ErrCode InputMethodSystemAbility::SwitchInputMethod( + uint32_t requestId, const std::string &bundleName, const std::string &subName, uint32_t trigger) +{ + CallerInfo callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, bundleName, subName, trigger, this]( + ServiceResponseData &, ActionInnerData &) -> int32_t { + return SwitchInputMethodTask(callerInfo, bundleName, subName, trigger); + }; + auto task = + std::make_shared(SaTaskCode::SWITCH_INPUT_METHOD, action, callerInfo, requester->imcResponseChannel); + return SaTaskManager::GetInstance().PostTask(task); } -ErrCode InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleName, - const std::string &subName, uint32_t trigger) +int32_t InputMethodSystemAbility::SwitchInputMethodTask( + const CallerInfo &callerInfo, const std::string &bundleName, const std::string &subName, uint32_t trigger) { // IMSA not check permission, add this verify for prevent counterfeit if (static_cast(trigger) == SwitchTrigger::IMSA) { IMSA_HILOGW("caller counterfeit!"); return ErrorCode::ERROR_BAD_PARAMETERS; } - SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName }; - int32_t userId = GetCallingUserId(); + SwitchInfo switchInfo = { bundleName, subName }; + int32_t userId = callerInfo.userId; auto session = UserSessionManager::GetInstance().GetUserSession(userId); if (session == nullptr) { IMSA_HILOGE("%{public}d session is nullptr!", userId); @@ -1119,7 +1248,7 @@ ErrCode InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleNam IMSA_HILOGW("ime %{public}s not enable, stopped!", bundleName.c_str()); return ErrorCode::ERROR_ENABLE_IME; } - if (identityChecker_->IsFormShell(IPCSkeleton::GetCallingFullTokenID()) && session->IsScreenLockOrSecurityFlag()) { + if (identityChecker_->IsFormShell(callerInfo.fullTokenId) && session->IsScreenLockOrSecurityFlag()) { IMSA_HILOGE("Screen is locked or current input is securityFlag, can not need switch input method!"); return ErrorCode::ERROR_SWITCH_IME; } @@ -1127,22 +1256,30 @@ ErrCode InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleNam if (switchInfo.subName.empty() && switchInfo.bundleName == currentImeCfg->bundleName) { switchInfo.subName = currentImeCfg->subName; } - switchInfo.timestamp = std::chrono::system_clock::now(); - session->GetSwitchQueue().Push(switchInfo); return InputTypeManager::GetInstance().IsInputType({ bundleName, subName }) - ? OnStartInputType(userId, switchInfo, true) - : OnSwitchInputMethod(userId, switchInfo, static_cast(trigger)); + ? OnStartInputType(callerInfo, switchInfo, true) + : OnSwitchInputMethod(callerInfo, switchInfo, static_cast(trigger)); } ErrCode InputMethodSystemAbility::EnableIme( - const std::string &bundleName, const std::string &extensionName, int32_t status) + uint32_t requestId, const std::string &bundleName, const std::string &extensionName, int32_t status) { - auto ret = CheckEnableAndSwitchPermission(); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("permission check failed!"); - return ret; - } - return EnableIme(GetCallingUserId(), bundleName, extensionName, static_cast(status)); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, bundleName, extensionName, status, this]( + ServiceResponseData &data, ActionInnerData &innerData) -> int32_t { + auto ret = CheckEnableAndSwitchPermission(callerInfo); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("permission check failed!"); + return ret; + } + return EnableIme(callerInfo.userId, bundleName, extensionName, static_cast(status)); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::ENABLE_IME, action, callerInfo, requester->imcResponseChannel)); } int32_t InputMethodSystemAbility::EnableIme( @@ -1152,11 +1289,11 @@ int32_t InputMethodSystemAbility::EnableIme( userId, bundleName, extensionName, static_cast(status)); } -bool InputMethodSystemAbility::IsOneTimeCodeSwitchSubtype(std::shared_ptr session, - const SwitchInfo &switchInfo) +bool InputMethodSystemAbility::IsOneTimeCodeSwitchSubtype(int32_t userId, const SwitchInfo &switchInfo) { + auto session = UserSessionManager::GetInstance().GetUserSession(userId); if (session == nullptr) { - IMSA_HILOGE("session is nullptr!"); + IMSA_HILOGE("%{public}d session is nullptr!", userId); return false; } @@ -1179,69 +1316,62 @@ bool InputMethodSystemAbility::IsOneTimeCodeSwitchSubtype(std::shared_ptr &session) +int32_t InputMethodSystemAbility::StartSwitch(int32_t userId, const SwitchInfo &switchInfo) { - if (session == nullptr) { - IMSA_HILOGE("session nullptr"); - return ErrorCode::ERROR_NULL_POINTER; - } IMSA_HILOGI("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str()); auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId, switchInfo.bundleName, switchInfo.subName); if (info == nullptr) { return ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED; } - if (!IsOneTimeCodeSwitchSubtype(session, switchInfo)) { + if (!IsOneTimeCodeSwitchSubtype(userId, switchInfo)) { InputTypeManager::GetInstance().Set(false); } - int32_t ret = 0; - { + + // 1 - generate StartIme action + auto doStart = [userId, name = info->prop.name, id = info->prop.id, switchInfo]( + ServiceResponseData &, ActionInnerData &) -> int32_t { InputMethodSyncTrace tracer("InputMethodSystemAbility_OnSwitchInputMethod"); - std::string targetImeName = info->prop.name + "/" + info->prop.id; + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_NULL_POINTER); + std::string targetImeName = name + "/" + id; ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, switchInfo.subName, true }); - auto targetIme = std::make_shared( - ImeNativeCfg{ targetImeName, info->prop.name, switchInfo.subName, info->prop.id }); - ret = session->StartIme(targetIme); - if (ret != ErrorCode::NO_ERROR) { - InputMethodSysEvent::GetInstance().InputmethodFaultReporter( - ret, switchInfo.bundleName, "switch input method failed!"); - return ret; - } + auto targetIme = std::make_shared(ImeNativeCfg{ targetImeName, name, switchInfo.subName, id }); + return session->StartIme(targetIme); + }; + auto onStartFailed = [ime = switchInfo.bundleName](int32_t ret) { + InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, ime, "switch input method failed!"); + }; + auto doStartAction = std::make_unique(doStart, nullptr, onStartFailed); + + // 2 - generate action after StartIme + auto afterStart = [this, userId, switchInfo, info](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_NULL_POINTER); GetValidSubtype(switchInfo.subName, info); session->NotifyImeChangeToClients(info->prop, info->subProp); - ret = session->SwitchSubtype(info->subProp); - } - ret = info->isSpecificSubName ? ret : ErrorCode::NO_ERROR; - if (ret != ErrorCode::NO_ERROR) { - InputMethodSysEvent::GetInstance().InputmethodFaultReporter( - ret, switchInfo.bundleName, "switch input method subtype failed!"); - } - return ret; + auto ret = session->SwitchSubtypeWithoutStartIme(info->subProp); + return info->isSpecificSubName ? ret : ErrorCode::NO_ERROR; + }; + auto onSwitchSubtypeFailed = [ime = switchInfo.bundleName](int32_t ret) { + InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, ime, "switch input method subtype failed!"); + }; + auto afterStartAction = std::make_unique(afterStart, nullptr, onSwitchSubtypeFailed); + + // pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(doStartAction), std::move(afterStartAction)); } -int32_t InputMethodSystemAbility::OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo, - SwitchTrigger trigger) +int32_t InputMethodSystemAbility::OnSwitchInputMethod( + const CallerInfo &callerInfo, const SwitchInfo &switchInfo, SwitchTrigger trigger) { InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - if (!session->GetSwitchQueue().IsReady(switchInfo)) { - IMSA_HILOGD("start wait."); - session->GetSwitchQueue().Wait(switchInfo); - } - int32_t ret = CheckSwitchPermission(userId, switchInfo, trigger); + int32_t ret = CheckSwitchPermission(switchInfo, trigger, callerInfo); if (ret != ErrorCode::NO_ERROR) { - InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED, - switchInfo.bundleName, "switch input method failed!"); - session->GetSwitchQueue().Pop(); + InputMethodSysEvent::GetInstance().InputmethodFaultReporter( + ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch input method failed!"); return ret; } - ret = StartSwitch(userId, switchInfo, session); - session->GetSwitchQueue().Pop(); - return ret; + return StartSwitch(callerInfo.userId, switchInfo); } void InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const std::shared_ptr &info) @@ -1253,36 +1383,22 @@ void InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const } } -int32_t InputMethodSystemAbility::OnStartInputType(int32_t userId, const SwitchInfo &switchInfo, - bool isCheckPermission) +int32_t InputMethodSystemAbility::OnStartInputType( + const CallerInfo &callerInfo, const SwitchInfo &switchInfo, bool isCheckPermission) { - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; - } - if (!session->GetSwitchQueue().IsReady(switchInfo)) { - IMSA_HILOGD("start wait."); - session->GetSwitchQueue().Wait(switchInfo); - } IMSA_HILOGD("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str()); - if (isCheckPermission && !IsStartInputTypePermitted(userId)) { + if (isCheckPermission && !IsStartInputTypePermitted(callerInfo, callerInfo.userId)) { IMSA_HILOGE("not permitted to start input type!"); - session->GetSwitchQueue().Pop(); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } - if (!IsNeedSwitch(userId, switchInfo.bundleName, switchInfo.subName)) { - IMSA_HILOGI("no need to switch."); - session->GetSwitchQueue().Pop(); + if (!IsNeedSwitch(callerInfo.userId, switchInfo.bundleName, switchInfo.subName)) { + IMSA_HILOGI("no need to switch"); return ErrorCode::NO_ERROR; } - int32_t ret = SwitchInputType(userId, switchInfo); - session->GetSwitchQueue().Pop(); - return ret; + return SwitchInputType(callerInfo.userId, switchInfo); } -bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName, - const std::string &subName) +bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName, const std::string &subName) { if (InputTypeManager::GetInstance().IsStarted()) { ImeIdentification target = { bundleName, subName }; @@ -1299,354 +1415,314 @@ bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &b return true; } -int32_t InputMethodSystemAbility::Switch(int32_t userId, const std::string &bundleName, - const std::shared_ptr &info) +int32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo) { - auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName; - if (bundleName != currentImeBundleName) { - IMSA_HILOGI("switch input method to: %{public}s", bundleName.c_str()); - return SwitchExtension(userId, info); - } - auto currentInputType = InputTypeManager::GetInstance().GetCurrentIme(); - auto isInputTypeStarted = InputTypeManager::GetInstance().IsStarted(); - if (isInputTypeStarted && bundleName != currentInputType.bundleName) { - IMSA_HILOGI("right click on state, switch input method to: %{public}s", bundleName.c_str()); - return SwitchExtension(userId, info); - } - return SwitchSubType(userId, info); -} + // 1 - generate StartIme action + auto doStart = [userId, switchInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + auto targetIme = session->GetImeNativeCfg(userId, switchInfo.bundleName, switchInfo.subName); + if (targetIme == nullptr) { + IMSA_HILOGE("targetIme is nullptr!"); + return ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED; + } + return session->StartIme(targetIme); + }; + auto onFailure = [](int32_t ret) { IMSA_HILOGE("start input method failed, ret: %{public}d!", ret); }; + auto doStartAction = std::make_unique(doStart, nullptr, onFailure); + + // 2 - generate action after StartIme + auto afterStart = [switchInfo, userId](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND); + SubProperty prop; + prop.name = switchInfo.bundleName; + prop.id = switchInfo.subName; + auto ret = session->SwitchSubtypeWithoutStartIme(prop); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("switch subtype failed!"); + return ret; + } + InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName }); + session->SetInputType(); + return ErrorCode::NO_ERROR; + }; -// Switch the current InputMethodExtension to the new InputMethodExtension -int32_t InputMethodSystemAbility::SwitchExtension(int32_t userId, const std::shared_ptr &info) -{ - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - std::string targetImeName = info->prop.name + "/" + info->prop.id; - ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, false }); - ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id }; - auto ret = session->StartIme(std::make_shared(targetIme)); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start input method failed!"); - return ret; - } - session->NotifyImeChangeToClients(info->prop, info->subProp); - GetValidSubtype("", info); - session->SwitchSubtype(info->subProp); - return ErrorCode::NO_ERROR; + // 3 - pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(doStartAction), afterStart); } -// Inform current InputMethodExtension to switch subtype -int32_t InputMethodSystemAbility::SwitchSubType(int32_t userId, const std::shared_ptr &info) -{ - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - auto ret = session->SwitchSubtype(info->subProp); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d!", ret); - return ret; - } - auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->imeId; - ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme, info->subProp.id, false }); - session->NotifyImeChangeToClients(info->prop, info->subProp); - return ErrorCode::NO_ERROR; +// Deprecated because of no permission check, kept for compatibility +int32_t InputMethodSystemAbility::HideCurrentInputDeprecated(uint32_t requestId) +{ + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + auto result = PrepareForOperateKeyboard(callerInfo, session); + if (result != ErrorCode::NO_ERROR) { + return result; + } + return session->OnHideCurrentInput(GetCallingDisplayId(callerInfo.pid)); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::HIDE_CURRENT_INPUT_DEPRECATED, action, callerInfo, requester->imcResponseChannel)); } -int32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo) +int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated(uint32_t requestId) { - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; - } - auto targetIme = session->GetImeNativeCfg(userId, switchInfo.bundleName, switchInfo.subName); - if (targetIme == nullptr) { - IMSA_HILOGE("targetIme is nullptr!"); - return ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED; - } - auto ret = session->StartIme(targetIme); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start input method failed!"); - return ret; - } - SubProperty prop; - prop.name = switchInfo.bundleName; - prop.id = switchInfo.subName; - ret = session->SwitchSubtype(prop); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("switch subtype failed!"); - return ret; - } - InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName }); - session->SetInputType(); - return ErrorCode::NO_ERROR; -} + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); -// Deprecated because of no permission check, kept for compatibility -int32_t InputMethodSystemAbility::HideCurrentInputDeprecated() -{ - std::shared_ptr session = nullptr; - auto result = PrepareForOperateKeyboard(session); - if (result != ErrorCode::NO_ERROR) { - return result; - } - return session->OnHideCurrentInput(GetCallingDisplayId()); + SaActionFunc action = [callerInfo, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr session = nullptr; + auto result = PrepareForOperateKeyboard(callerInfo, session); + if (result != ErrorCode::NO_ERROR) { + return result; + } + return session->OnShowCurrentInput(GetCallingDisplayId(callerInfo.pid)); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::SHOW_CURRENT_INPUT_DEPRECATED, action, callerInfo, requester->imcResponseChannel)); } -int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated() +ErrCode InputMethodSystemAbility::GetCurrentInputMethod(uint32_t requestId) { - std::shared_ptr session = nullptr; - auto result = PrepareForOperateKeyboard(session); - if (result != ErrorCode::NO_ERROR) { - return result; - } - return session->OnShowCurrentInput(GetCallingDisplayId()); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + auto prop = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(callerInfo.userId); + if (prop == nullptr) { + IMSA_HILOGE("prop is nullptr!"); + return ErrorCode::ERROR_NULL_POINTER; + } + data = *prop; + return ERR_OK; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::GET_CURRENT_INPUT_METHOD, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::GetCurrentInputMethod(Property& resultValue) +ErrCode InputMethodSystemAbility::IsDefaultImeSet(uint32_t requestId) { - auto prop = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(GetCallingUserId()); - if (prop == nullptr) { - IMSA_HILOGE("prop is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - resultValue = *prop; - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + bool resultValue = ImeInfoInquirer::GetInstance().IsDefaultImeSet(callerInfo.userId); + data = resultValue; + return ERR_OK; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::IS_DEFAULT_IME_SET, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::IsDefaultImeSet(bool& resultValue) +ErrCode InputMethodSystemAbility::GetCurrentInputMethodSubtype(uint32_t requestId) { - resultValue = ImeInfoInquirer::GetInstance().IsDefaultImeSet(GetCallingUserId()); - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + auto prop = ImeInfoInquirer::GetInstance().GetCurrentSubtype(callerInfo.userId); + if (prop == nullptr) { + IMSA_HILOGE("prop is nullptr!"); + return ErrorCode::ERROR_NULL_POINTER; + } + data = *prop; + return ERR_OK; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::GET_CURRENT_INPUT_METHOD_SUBTYPE, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::GetCurrentInputMethodSubtype(SubProperty& resultValue) +ErrCode InputMethodSystemAbility::GetDefaultInputMethod(uint32_t requestId, bool isBrief) { - auto prop = ImeInfoInquirer::GetInstance().GetCurrentSubtype(GetCallingUserId()); - if (prop == nullptr) { - IMSA_HILOGE("prop is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - resultValue = *prop; - return ERR_OK; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, isBrief](ServiceResponseData &data, ActionInnerData &) -> int32_t { + std::shared_ptr property = std::make_shared(); + auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(callerInfo.userId, property, isBrief); + if (ret == ErrorCode::NO_ERROR) { + data = *property; + } + return ret; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::GET_DEFAULT_INPUT_METHOD, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::GetDefaultInputMethod(Property &prop, bool isBrief) +ErrCode InputMethodSystemAbility::GetInputMethodConfig(uint32_t requestId) { - std::shared_ptr property = std::make_shared(prop); - auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(GetCallingUserId(), property, isBrief); - if (ret == ErrorCode::NO_ERROR) { - prop = *property; - } - return ret; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo](ServiceResponseData &data, ActionInnerData &) -> int32_t { + AppExecFwk::ElementName inputMethodConfig; + auto ret = ImeInfoInquirer::GetInstance().GetInputMethodConfig(callerInfo.userId, inputMethodConfig); + if (ret == ErrorCode::NO_ERROR) { + data = inputMethodConfig; + } + return ret; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::GET_INPUT_METHOD_CONFIG, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::GetInputMethodConfig(ElementName &inputMethodConfig) +ErrCode InputMethodSystemAbility::ListInputMethod(uint32_t requestId, uint32_t status) { - return ImeInfoInquirer::GetInstance().GetInputMethodConfig(GetCallingUserId(), inputMethodConfig); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, status](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::vector props; + return ImeInfoInquirer::GetInstance().ListInputMethod( + callerInfo.userId, static_cast(status), props); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::LIST_INPUT_METHOD, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::ListInputMethod(uint32_t status, std::vector &props) +ErrCode InputMethodSystemAbility::ListCurrentInputMethodSubtype(uint32_t requestId) { - return ImeInfoInquirer::GetInstance().ListInputMethod(GetCallingUserId(), - static_cast(status), props); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::vector subProps; + return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(callerInfo.userId, subProps); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::LIST_CURRENT_INPUT_METHOD_SUBTYPE, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector &subProps) +int32_t InputMethodSystemAbility::ListInputMethodSubtype(uint32_t requestId, const std::string &bundleName) { - return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(GetCallingUserId(), subProps); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, bundleName](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::vector subProps; + return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(callerInfo.userId, bundleName, subProps); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::LIST_INPUT_METHOD_SUBTYPE, action, callerInfo, requester->imcResponseChannel)); } -int32_t InputMethodSystemAbility::ListInputMethodSubtype(const std::string &bundleName, - std::vector &subProps) +int32_t InputMethodSystemAbility::OnUserStarted(const EventFwk::CommonEventData &data) { - return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(GetCallingUserId(), bundleName, subProps); + auto newUserId = data.GetCode(); + FullImeInfoManager::GetInstance().Switch(newUserId); + // if scb enable, deal when receive wmsConnected. + if (isScbEnable_.load()) { + return ErrorCode::NO_ERROR; + } + if (newUserId == userId_) { + return ErrorCode::NO_ERROR; + } + HandleUserSwitched(newUserId); + return ErrorCode::NO_ERROR; } -/** - * Work Thread of input method management service - * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread. - */ -void InputMethodSystemAbility::WorkThread() -{ - pthread_setname_np(pthread_self(), "OS_IMSAWorkThread"); - while (!stop_) { - Message *msg = MessageHandler::Instance()->GetMessage(); - switch (msg->msgId_) { - case MSG_ID_USER_START: { - OnUserStarted(msg); - break; - } - case MSG_ID_USER_REMOVED: { - OnUserRemoved(msg); - break; - } - case MSG_ID_USER_STOP: { - OnUserStop(msg); - break; - } - case MSG_ID_HIDE_KEYBOARD_SELF: { - OnHideKeyboardSelf(msg); - break; - } - case MSG_ID_BUNDLE_SCAN_FINISHED: { - HandleBundleScanFinished(); - break; - } - case MSG_ID_DATA_SHARE_READY: { - HandleDataShareReady(); - break; - } - case MSG_ID_PACKAGE_ADDED: - case MSG_ID_PACKAGE_CHANGED: - case MSG_ID_PACKAGE_REMOVED: { - HandlePackageEvent(msg); - break; - } - case MSG_ID_SYS_LANGUAGE_CHANGED: { - FullImeInfoManager::GetInstance().Update(); - break; - } - case MSG_ID_BOOT_COMPLETED: - case MSG_ID_OS_ACCOUNT_STARTED: { - FullImeInfoManager::GetInstance().Init(); - break; - } - case MSG_ID_SCREEN_UNLOCK: { - OnScreenUnlock(msg); - break; - } - case MSG_ID_REGULAR_UPDATE_IME_INFO: { - FullImeInfoManager::GetInstance().RegularInit(); - break; - } - default: { - IMSA_HILOGD("the message is %{public}d.", msg->msgId_); - break; - } - } - delete msg; - } -} - -/** - * Called when a user is started. (EVENT_USER_STARTED is received) - * \n Run in work thread of input method management service - * \param msg the parameters are saved in msg->msgContent_ - * \return ErrorCode - */ -int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg) +int32_t InputMethodSystemAbility::OnUserRemoved(const EventFwk::CommonEventData &data) { - if (msg->msgContent_ == nullptr) { - IMSA_HILOGE("msgContent_ is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - auto newUserId = msg->msgContent_->ReadInt32(); - FullImeInfoManager::GetInstance().Switch(newUserId); - // if scb enable, deal when receive wmsConnected. - if (isScbEnable_.load()) { - return ErrorCode::NO_ERROR; - } - if (newUserId == userId_) { + auto userId = data.GetCode(); + IMSA_HILOGI("start: %{public}d", userId); + // 1 - generate StopIme action + auto doStopIme = [userId](ServiceResponseData &, ActionInnerData &) -> int32_t { + auto session = UserSessionManager::GetInstance().GetUserSession(userId); + if (session == nullptr) { + return ErrorCode::NO_ERROR; + } + return session->StopCurrentIme(); + }; + auto stopImeAction = std::make_unique(doStopIme, nullptr, nullptr, false); + // 2 - generate RemoveData action + auto doRemoveData = [userId](ServiceResponseData &, ActionInnerData &) { + UserSessionManager::GetInstance().RemoveUserSession(userId); + FullImeInfoManager::GetInstance().Delete(userId); + NumkeyAppsManager::GetInstance().OnUserRemoved(userId); return ErrorCode::NO_ERROR; - } - HandleUserSwitched(newUserId); - return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().Pend(std::move(stopImeAction), doRemoveData); } -int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg) +int32_t InputMethodSystemAbility::OnUserStop(const EventFwk::CommonEventData &data) { - if (msg == nullptr || msg->msgContent_ == nullptr) { - IMSA_HILOGE("Aborted! Message is nullptr!"); - return ErrorCode::ERROR_NULL_POINTER; - } - auto userId = msg->msgContent_->ReadInt32(); + auto userId = data.GetCode(); IMSA_HILOGI("start: %{public}d", userId); auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session != nullptr) { - session->StopCurrentIme(); - UserSessionManager::GetInstance().RemoveUserSession(userId); - } - FullImeInfoManager::GetInstance().Delete(userId); - NumkeyAppsManager::GetInstance().OnUserRemoved(userId); - return ErrorCode::NO_ERROR; -} - -int32_t InputMethodSystemAbility::OnUserStop(const Message *msg) -{ - auto session = GetSessionFromMsg(msg); if (session == nullptr) { - return ErrorCode::ERROR_NULL_POINTER; + IMSA_HILOGE("%{public}d session is nullptr!", userId); + return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; } - session->StopCurrentIme(); - return ErrorCode::NO_ERROR; + auto doStop = [userId, session](ServiceResponseData &, ActionInnerData &) { return session->StopCurrentIme(); }; + auto stopAction = std::make_unique(doStop, nullptr, nullptr, false); + return SaTaskManager::GetInstance().Pend(std::move(stopAction)); } -int32_t InputMethodSystemAbility::OnHideKeyboardSelf(const Message *msg) +void InputMethodSystemAbility::OnPackageAdded(const EventFwk::CommonEventData &data) { - auto session = GetSessionFromMsg(msg); - if (session == nullptr) { - return ErrorCode::ERROR_NULL_POINTER; + auto const &want = data.GetWant(); + auto bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); + if (userId == OsAccountAdapter::INVALID_USER_ID) { + IMSA_HILOGE("invalid user id"); + return; } - session->OnHideSoftKeyBoardSelf(); - return ErrorCode::NO_ERROR; + FullImeInfoManager::GetInstance().Add(userId, bundleName); } -int32_t InputMethodSystemAbility::HandlePackageEvent(const Message *msg) +void InputMethodSystemAbility::OnPackageChanged(const EventFwk::CommonEventData &data) { - MessageParcel *data = msg->msgContent_; - if (data == nullptr) { - IMSA_HILOGD("data is nullptr"); - return ErrorCode::ERROR_NULL_POINTER; - } - int32_t userId = 0; - std::string packageName; - if (!ITypesUtil::Unmarshal(*data, userId, packageName)) { - IMSA_HILOGE("Failed to read message parcel!"); - return ErrorCode::ERROR_EX_PARCELABLE; - } - if (msg->msgId_ == MSG_ID_PACKAGE_CHANGED) { - return FullImeInfoManager::GetInstance().Update(userId, packageName); - } - if (msg->msgId_ == MSG_ID_PACKAGE_ADDED) { - return FullImeInfoManager::GetInstance().Add(userId, packageName); - } - if (msg->msgId_ == MSG_ID_PACKAGE_REMOVED) { - return OnPackageRemoved(userId, packageName); + auto const &want = data.GetWant(); + auto bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); + if (userId == OsAccountAdapter::INVALID_USER_ID) { + IMSA_HILOGE("invalid user id"); + return; } - return ErrorCode::NO_ERROR; + FullImeInfoManager::GetInstance().Update(userId, bundleName); } -/** - * Called when a package is removed. - * \n Run in work thread of input method management service - * \param msg the parameters are saved in msg->msgContent_ - * \return ErrorCode::NO_ERROR - * \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked - * \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter - */ -int32_t InputMethodSystemAbility::OnPackageRemoved(int32_t userId, const std::string &packageName) +void InputMethodSystemAbility::OnPackageRemoved(const EventFwk::CommonEventData &data) { - FullImeInfoManager::GetInstance().Delete(userId, packageName); - return ErrorCode::NO_ERROR; + auto const &want = data.GetWant(); + auto bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); + if (userId == OsAccountAdapter::INVALID_USER_ID) { + IMSA_HILOGE("invalid user id"); + return; + } + FullImeInfoManager::GetInstance().Delete(userId, bundleName); } -void InputMethodSystemAbility::OnScreenUnlock(const Message *msg) +void InputMethodSystemAbility::OnScreenUnlock(const EventFwk::CommonEventData &data) { - if (msg == nullptr || msg->msgContent_ == nullptr) { - IMSA_HILOGE("message is nullptr"); - return; - } - int32_t userId = 0; - if (!ITypesUtil::Unmarshal(*msg->msgContent_, userId)) { - IMSA_HILOGE("failed to read message"); - return; - } + auto const &want = data.GetWant(); + int32_t userId = want.GetIntParam("userId", OsAccountAdapter::INVALID_USER_ID); IMSA_HILOGI("userId: %{public}d", userId); if (userId != userId_) { return; @@ -1724,7 +1800,8 @@ void InputMethodSystemAbility::DealSwitchRequest() ++targetSwitchCount_; } } - auto switchTask = [this]() { + + SaActionFunc switchTask = [this](ServiceResponseData &, ActionInnerData &) -> int32_t { auto checkSwitchCount = [this]() { std::lock_guard lock(switchImeMutex_); if (targetSwitchCount_ > 0) { @@ -1736,9 +1813,9 @@ void InputMethodSystemAbility::DealSwitchRequest() do { SwitchType(); } while (checkSwitchCount()); + return ErrorCode::NO_ERROR; }; - // 0 means delay time is 0. - serviceHandler_->PostTask(switchTask, "SwitchImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::SWITCH_INPUT_METHOD, switchTask)); } int32_t InputMethodSystemAbility::SwitchMode() @@ -1780,14 +1857,13 @@ int32_t InputMethodSystemAbility::SwitchLanguage() int32_t InputMethodSystemAbility::SwitchType() { - SwitchInfo nextSwitchInfo = { std::chrono::system_clock::now(), "", "" }; uint32_t cacheCount = 0; { std::lock_guard lock(switchImeMutex_); cacheCount = targetSwitchCount_.exchange(0); } - int32_t ret = - ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(nextSwitchInfo, userId_, cacheCount); + SwitchInfo nextSwitchInfo; + int32_t ret = ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(nextSwitchInfo, userId_, cacheCount); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("get next SwitchInfo failed, stop switching ime."); return ret; @@ -1797,33 +1873,58 @@ int32_t InputMethodSystemAbility::SwitchType() return ErrorCode::NO_ERROR; } IMSA_HILOGD("switch to: %{public}s.", nextSwitchInfo.bundleName.c_str()); - nextSwitchInfo.timestamp = std::chrono::system_clock::now(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId_); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId_); - return ErrorCode::ERROR_NULL_POINTER; - } - session->GetSwitchQueue().Push(nextSwitchInfo); - return OnSwitchInputMethod(userId_, nextSwitchInfo, SwitchTrigger::IMSA); + return OnSwitchInputMethod({ .userId = userId_ }, nextSwitchInfo, SwitchTrigger::IMSA); } void InputMethodSystemAbility::InitMonitors() { - int32_t ret = InitAccountMonitor(); - IMSA_HILOGI("init account monitor, ret: %{public}d.", ret); - SubscribeCommonEvent(); - ret = InitMemMgrMonitor(); - IMSA_HILOGI("init MemMgr monitor, ret: %{public}d.", ret); - ret = InitKeyEventMonitor(); - IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d.", ret); - ret = InitWmsMonitor(); - IMSA_HILOGI("init wms monitor, ret: %{public}d.", ret); - ret = InitPasteboardMonitor(); - IMSA_HILOGI("init Pasteboard monitor, ret: %{public}d.", ret); + // subscribe sa status change listeners + SubscribeSaListeners(); InitSystemLanguageMonitor(); } -void InputMethodSystemAbility::HandleDataShareReady() +void InputMethodSystemAbility::SubscribeSaListeners() +{ + // set callbacks + ImCommonEventManager::GetInstance().RegisterSaHandler( + SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN, [this] { HandleOsAccountStarted(); }); + ImCommonEventManager::GetInstance().RegisterSaHandler(MEMORY_MANAGER_SA_ID, [this] { HandleMemStarted(); }); + ImCommonEventManager::GetInstance().RegisterSaHandler(MULTIMODAL_INPUT_SERVICE_ID, [this] { HandleMMIStarted(); }); + ImCommonEventManager::GetInstance().RegisterSaHandler(WINDOW_MANAGER_SERVICE_ID, [this] { HandleWmsStarted(); }); + ImCommonEventManager::GetInstance().RegisterSaHandler(COMMON_EVENT_SERVICE_ID, [this] { SubscribeCommonEvents(); }); + ImCommonEventManager::GetInstance().RegisterSaHandler(PASTEBOARD_SERVICE_ID, [this] { HandlePasteboardStarted(); }); + + // subscribe + ImCommonEventManager::GetInstance().SubscribeSaStatus(); +} + +void InputMethodSystemAbility::SubscribeCommonEvents() +{ + // set callbacks + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_USER_SWITCHED, + [this](const EventFwk::CommonEventData &data) { OnUserStarted(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_USER_REMOVED, + [this](const EventFwk::CommonEventData &data) { OnUserRemoved(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_USER_STOPPED, + [this](const EventFwk::CommonEventData &data) { OnUserStop(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, + [this](const EventFwk::CommonEventData &data) { OnPackageAdded(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, + [this](const EventFwk::CommonEventData &data) { OnPackageChanged(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, + [this](const EventFwk::CommonEventData &data) { OnPackageRemoved(data); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, + [this](const EventFwk::CommonEventData &data) { OnBundleScanFinished(); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_DATA_SHARE_READY, + [this](const EventFwk::CommonEventData &data) { OnDataShareReady(); }); + ImCommonEventManager::GetInstance().RegisterEventHandler(CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED, + [this](const EventFwk::CommonEventData &data) { OnScreenUnlock(data); }); + + // subscribe + ImCommonEventManager::GetInstance().SubscribeEvents(); +} + +void InputMethodSystemAbility::OnDataShareReady() { IMSA_HILOGI("run in."); if (ImeInfoInquirer::GetInstance().GetSystemConfig().enableFullExperienceFeature) { @@ -1838,37 +1939,14 @@ void InputMethodSystemAbility::HandleDataShareReady() NumkeyAppsManager::GetInstance().Init(userId_); } -int32_t InputMethodSystemAbility::InitAccountMonitor() +void InputMethodSystemAbility::HandleMMIStarted() { - IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor start."); - return ImCommonEventManager::GetInstance()->SubscribeAccountManagerService([this]() { HandleOsAccountStarted(); }); -} - -int32_t InputMethodSystemAbility::InitKeyEventMonitor() -{ - IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor start."); - auto handler = [this]() { - auto switchTrigger = [this](uint32_t keyCode) { - return SwitchByCombinationKey(keyCode); - }; - int32_t ret = KeyboardEvent::GetInstance().AddKeyEventMonitor(switchTrigger); - IMSA_HILOGI( - "SubscribeKeyboardEvent add monitor: %{public}s.", ret == ErrorCode::NO_ERROR ? "success" : "failed"); - // Check device capslock status and ime cfg corrent, when device power-up. - HandleImeCfgCapsState(); - }; - bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent(handler); - return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED; -} - -bool InputMethodSystemAbility::InitWmsMonitor() -{ - return ImCommonEventManager::GetInstance()->SubscribeWindowManagerService([this]() { HandleWmsStarted(); }); -} - -bool InputMethodSystemAbility::InitMemMgrMonitor() -{ - return ImCommonEventManager::GetInstance()->SubscribeMemMgrService([this]() { HandleMemStarted(); }); + IMSA_HILOGI("start"); + auto switchTrigger = [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); }; + int32_t ret = KeyboardEvent::GetInstance().AddKeyEventMonitor(switchTrigger); + IMSA_HILOGI("AddKeyEventMonitor ret %{public}d", ret); + // Check device caps Lock status and correct ime cfg, when device power-up. + HandleImeCfgCapsState(); } void InputMethodSystemAbility::InitWmsConnectionMonitor() @@ -1902,19 +1980,6 @@ void InputMethodSystemAbility::HandlePasteboardStarted() data->imeStateManager->PasteBoardActiveIme(); } -bool InputMethodSystemAbility::InitPasteboardMonitor() -{ - auto commonEventMgr = ImCommonEventManager::GetInstance(); - if (commonEventMgr == nullptr) { - IMSA_HILOGE("commonEventMgr is nullptr."); - return false; - } - - return commonEventMgr->SubscribePasteboardService([this]() { - HandlePasteboardStarted(); - }); -} - void InputMethodSystemAbility::InitSystemLanguageMonitor() { SystemLanguageObserver::GetInstance().Watch(); @@ -1930,18 +1995,22 @@ void InputMethodSystemAbility::InitFocusChangedMonitor() void InputMethodSystemAbility::InitWindowDisplayChangedMonitor() { IMSA_HILOGD("enter."); - auto callBack = [this](OHOS::Rosen::CallingWindowInfo callingWindowInfo) { - IMSA_HILOGD("WindowDisplayChanged callbak."); + auto callBack = [this](Rosen::CallingWindowInfo callingWindowInfo) { HandleDisplayChanged(callingWindowInfo); }; + WindowAdapter::GetInstance().RegisterCallingWindowInfoChangedListener(callBack); +} + +void InputMethodSystemAbility::HandleDisplayChanged(const Rosen::CallingWindowInfo &callingWindowInfo) +{ + IMSA_HILOGD("WindowDisplayChanged callback."); + auto func = [callingWindowInfo](ServiceResponseData &, ActionInnerData) { int32_t userId = callingWindowInfo.userId_; - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("[%{public}d] session is nullptr!", userId); - return; - }; + std::shared_ptr session = nullptr; + GET_USER_SESSION(userId, session, ErrorCode::ERROR_NULL_POINTER); session->OnCallingDisplayIdChanged( callingWindowInfo.windowId_, callingWindowInfo.callingPid_, callingWindowInfo.displayId_); + return ErrorCode::NO_ERROR; }; - WindowAdapter::GetInstance().RegisterCallingWindowInfoChangedListener(callBack); + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_DISPLAY_ID_CHANGED, func)); } void InputMethodSystemAbility::RegisterSecurityModeObserver() @@ -1956,12 +2025,12 @@ void InputMethodSystemAbility::DataShareCallback(const std::string &key) if (key != SettingsDataUtils::SECURITY_MODE) { return; } - IMSA_HILOGI("%{public}d full experience change.", userId_); - if (serviceHandler_ == nullptr) { - return; - } - auto task = [userId = userId_]() { ImeEnabledInfoManager::GetInstance().OnFullExperienceTableChanged(userId); }; - serviceHandler_->PostTask(task, "OnFullExperienceTableChanged", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); + SaActionFunc func = [userId = userId_](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("%{public}d full experience change.", userId); + ImeEnabledInfoManager::GetInstance().OnFullExperienceTableChanged(userId); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_DATA_SHARE_CALLBACK, func)); } void InputMethodSystemAbility::OnCurrentImeStatusChanged( @@ -1988,92 +2057,72 @@ void InputMethodSystemAbility::OnCurrentImeStatusChanged( session->AddRestartIme(); } -int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security) +int32_t InputMethodSystemAbility::GetSecurityMode(uint32_t requestId) { - IMSA_HILOGD("InputMethodSystemAbility start."); - auto userId = GetCallingUserId(); - auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID()); - if (bundleName.empty()) { - bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID()); - if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) { - IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str()); - return ErrorCode::ERROR_NOT_IME; - } - } - security = static_cast(SecurityMode::BASIC); - EnabledStatus status = EnabledStatus::BASIC_MODE; - auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, status); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGW("[%{public}d, %{public}s] get enabled status failed:%{public}d,!", userId, bundleName.c_str(), ret); - } - if (status == EnabledStatus::FULL_EXPERIENCE_MODE) { - security = static_cast(SecurityMode::FULL); - } - return ErrorCode::NO_ERROR; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &data, ActionInnerData &) -> int32_t { + int32_t securityMode = 0; + auto ret = GetSecurityModeTask(callerInfo, securityMode); + data = securityMode; + return ret; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::GET_SECURITY_MODE, action, callerInfo, requester->imaResponseChannel)); } -ErrCode InputMethodSystemAbility::UnRegisteredProxyIme(int32_t type, const sptr &core) +ErrCode InputMethodSystemAbility::UnRegisteredProxyIme( + uint32_t requestId, int32_t type, const sptr &core) { - if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - IMSA_HILOGE("not native sa!"); - return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - if (static_cast(type) == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) { - int32_t ret = ErrorCode::NO_ERROR; - if (session->CheckSecurityMode()) { - ret = StartInputType(userId, InputType::SECURITY_INPUT); - } else { - ret = session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); - } - if (ret != ErrorCode::NO_ERROR) { - return ret; - } - } - return session->OnUnRegisteredProxyIme(static_cast(type), core); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imaResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, type, core, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return UnRegisteredProxyImeTask(callerInfo, type, core); + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::UNREGISTERED_PROXY_IME, action, callerInfo, requester->imaResponseChannel)); } -int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission() +int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission(const CallerInfo &callerInfo) { - if (identityChecker_->IsFormShell(IPCSkeleton::GetCallingFullTokenID())) { + if (identityChecker_->IsFormShell(callerInfo.fullTokenId)) { IMSA_HILOGD("is form shell!"); return ErrorCode::NO_ERROR; } - if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingFullTokenID()) && - !identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) { + if (!identityChecker_->IsNativeSa(callerInfo.fullTokenId) + && !identityChecker_->IsSystemApp(callerInfo.fullTokenId)) { IMSA_HILOGE("not native sa or system app!"); return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; } - if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), - std::string(PERMISSION_CONNECT_IME_ABILITY))) { + if (!identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!"); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } return ErrorCode::NO_ERROR; } -int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo, - SwitchTrigger trigger) +int32_t InputMethodSystemAbility::CheckSwitchPermission( + const SwitchInfo &switchInfo, SwitchTrigger trigger, const CallerInfo &callerInfo) { IMSA_HILOGD("trigger: %{public}d.", static_cast(trigger)); if (trigger == SwitchTrigger::IMSA) { return ErrorCode::NO_ERROR; } if (trigger == SwitchTrigger::NATIVE_SA) { - return CheckEnableAndSwitchPermission(); + return CheckEnableAndSwitchPermission(callerInfo); } if (trigger == SwitchTrigger::SYSTEM_APP) { - if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) { + if (!identityChecker_->IsSystemApp(callerInfo.fullTokenId)) { IMSA_HILOGE("not system app!"); return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; } - if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), - std::string(PERMISSION_CONNECT_IME_ABILITY))) { + if (!identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!"); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } @@ -2081,14 +2130,13 @@ int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const Sw } if (trigger == SwitchTrigger::CURRENT_IME) { // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon - if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), - std::string(PERMISSION_CONNECT_IME_ABILITY))) { + if (identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { return ErrorCode::NO_ERROR; } IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!"); // switchInfo.subName.empty() check temporarily reserved for application adaptation, will be deleted soon - auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName; - if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName)) { + auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(callerInfo.userId)->bundleName; + if (identityChecker_->IsBundleNameValid(callerInfo.tokenId, currentBundleName)) { return ErrorCode::NO_ERROR; } IMSA_HILOGE("not current ime!"); @@ -2099,14 +2147,14 @@ int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const Sw return ErrorCode::ERROR_BAD_PARAMETERS; } -bool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId) +bool InputMethodSystemAbility::IsStartInputTypePermitted(const CallerInfo &callerInfo, int32_t userId) { auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId); if (defaultIme == nullptr) { IMSA_HILOGE("failed to get default ime!"); return false; } - auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto tokenId = callerInfo.tokenId; if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) { return true; } @@ -2118,28 +2166,30 @@ bool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId) IMSA_HILOGE("%{public}d session is nullptr!", userId); return false; } - return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) - && session->IsBoundToClient(GetCallingDisplayId()); + return identityChecker_->IsFocused(callerInfo.pid, tokenId) + && session->IsBoundToClient(GetCallingDisplayId(callerInfo.pid)); } -int32_t InputMethodSystemAbility::ConnectSystemCmd(const sptr &channel, sptr &agent) +int32_t InputMethodSystemAbility::ConnectSystemCmd(uint32_t requestId, const sptr &channel) { - auto tokenId = IPCSkeleton::GetCallingTokenID(); - if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { - IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!"); - return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; - } - auto userId = GetCallingUserId(); - auto session = UserSessionManager::GetInstance().GetUserSession(userId); - if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); - return ErrorCode::ERROR_NULL_POINTER; - } - return session->OnConnectSystemCmd(channel, agent); + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [this, callerInfo, channel](ServiceResponseData &data, ActionInnerData &) -> int32_t { + sptr agent = nullptr; + auto ret = ConnectSystemCmdTask(callerInfo, channel, agent); + data = agent; + return ret; + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::CONNECT_SYSTEM_CMD, action, callerInfo, requester->imcResponseChannel)); } void InputMethodSystemAbility::HandleWmsConnected(int32_t userId, int32_t screenId) { + IMSA_HILOGI("userId: %{public}d, screenId: %{public}d", userId, screenId); if (userId == userId_) { // device boot or scb in foreground reboot HandleScbStarted(userId, screenId); @@ -2187,6 +2237,7 @@ void InputMethodSystemAbility::HandleUserSwitched(int32_t userId) void InputMethodSystemAbility::HandleWmsDisconnected(int32_t userId, int32_t screenId) { + IMSA_HILOGI("userId: %{public}d, screenId: %{public}d", userId, screenId); // clear client auto session = UserSessionManager::GetInstance().GetUserSession(userId); if (session != nullptr) { @@ -2247,32 +2298,36 @@ void InputMethodSystemAbility::HandleMemStarted() void InputMethodSystemAbility::HandleOsAccountStarted() { - IMSA_HILOGI("account start"); auto userId = OsAccountAdapter::GetForegroundOsAccountLocalId(); if (userId_ != userId) { UpdateUserInfo(userId); } - Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_OS_ACCOUNT_STARTED, nullptr); - if (msg == nullptr) { - return; - } - MessageHandler::Instance()->SendMessage(msg); + FullImeInfoManager::GetInstance().Init(); } void InputMethodSystemAbility::StopImeInBackground() { - auto task = [this]() { - auto sessions = UserSessionManager::GetInstance().GetUserSessions(); - for (const auto &tempSession : sessions) { - if (tempSession.first != userId_) { - tempSession.second->StopCurrentIme(); - } + auto sessions = UserSessionManager::GetInstance().GetUserSessions(); + for (const auto &session : sessions) { + if (session.first != userId_) { + auto doStop = [userSession = session.second](ServiceResponseData &, ActionInnerData &) { + return userSession->StopCurrentIme(); + }; + auto stopAction = std::make_unique(doStop, nullptr, nullptr, false); + SaTaskManager::GetInstance().Pend(std::move(stopAction)); } - }; - if (serviceHandler_ == nullptr) { - return; } - serviceHandler_->PostTask(task, "StopImeInBackground", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); +} + +CallerInfo InputMethodSystemAbility::GetCallerInfo(uint32_t requestId) +{ + auto uid = IPCSkeleton::GetCallingUid(); + return { .requestId = requestId, + .pid = IPCSkeleton::GetCallingPid(), + .uid = uid, + .userId = GetUserId(uid), + .tokenId = IPCSkeleton::GetCallingTokenID(), + .fullTokenId = IPCSkeleton::GetCallingFullTokenID() }; } int32_t InputMethodSystemAbility::GetUserId(int32_t uid) @@ -2293,35 +2348,35 @@ int32_t InputMethodSystemAbility::GetCallingUserId() return GetUserId(uid); } -uint64_t InputMethodSystemAbility::GetCallingDisplayId(sptr abilityToken) +uint64_t InputMethodSystemAbility::GetCallingDisplayId(int32_t callingPid, sptr abilityToken) { - return identityChecker_->GetDisplayIdByPid(IPCSkeleton::GetCallingPid(), abilityToken); + return identityChecker_->GetDisplayIdByPid(callingPid, abilityToken); } -bool InputMethodSystemAbility::IsCurrentIme(int32_t userId) +bool InputMethodSystemAbility::IsCurrentIme(const CallerInfo &callerInfo) { - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return false; } - auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID()); + auto bundleName = FullImeInfoManager::GetInstance().Get(callerInfo.userId, callerInfo.tokenId); if (bundleName.empty()) { - IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", userId, IPCSkeleton::GetCallingTokenID()); - bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID()); + IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", callerInfo.userId, callerInfo.tokenId); + bundleName = identityChecker_->GetBundleNameByToken(callerInfo.tokenId); } auto imeData = session->GetImeData(ImeType::IME); return imeData != nullptr && bundleName == imeData->ime.first; } -int32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type) +int32_t InputMethodSystemAbility::StartInputType(const CallerInfo &callerInfo, InputType type) { - auto session = UserSessionManager::GetInstance().GetUserSession(userId); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); if (session == nullptr) { - IMSA_HILOGE("%{public}d session is nullptr!", userId); + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND; } - if (!session->IsDefaultDisplayGroup(GetCallingDisplayId())) { + if (!session->IsDefaultDisplayGroup(GetCallingDisplayId(callerInfo.pid))) { IMSA_HILOGI("only need input type in default display"); return ErrorCode::NO_ERROR; } @@ -2335,11 +2390,11 @@ int32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type) } return ret; } - SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName }; - session->GetSwitchQueue().Push(switchInfo); + SwitchInfo switchInfo = { ime.bundleName, ime.subName }; IMSA_HILOGI("start input type: %{public}d.", type); - return (type == InputType::SECURITY_INPUT || type == InputType::ONE_TIME_CODE) ? - OnStartInputType(userId, switchInfo, false) : OnStartInputType(userId, switchInfo, true); + return (type == InputType::SECURITY_INPUT || type == InputType::ONE_TIME_CODE) + ? OnStartInputType(callerInfo, switchInfo, false) + : OnStartInputType(callerInfo, switchInfo, true); } void InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, InputType type, bool &needHide) @@ -2364,7 +2419,7 @@ void InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, Input needHide = imeData->ime.first == ime.bundleName; } -void InputMethodSystemAbility::HandleBundleScanFinished() +void InputMethodSystemAbility::OnBundleScanFinished() { isBundleScanFinished_.store(true); HandleImeCfgCapsState(); @@ -2441,66 +2496,64 @@ void InputMethodSystemAbility::HandleImeCfgCapsState() } } -ErrCode InputMethodSystemAbility::GetInputMethodState(int32_t& status) +ErrCode InputMethodSystemAbility::GetInputMethodState(uint32_t requestId) { - auto userId = GetCallingUserId(); - auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID()); - if (bundleName.empty()) { - bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID()); - if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) { - IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str()); - return ErrorCode::ERROR_NOT_IME; - } - } - EnabledStatus tmpStatus = EnabledStatus::DISABLED; - auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, tmpStatus); - if (ret != ErrorCode::NO_ERROR) { + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, this](ServiceResponseData &data, ActionInnerData &) -> int32_t { + int32_t status = 0; + auto ret = GetInputMethodStateTask(callerInfo, status); + data = status; return ret; - } - status = static_cast(tmpStatus); - return ErrorCode::NO_ERROR; + }; + return SaTaskManager::GetInstance().PostTask(std::make_shared( + SaTaskCode::GET_INPUT_METHOD_STATE, action, callerInfo, requester->imcResponseChannel)); } -ErrCode InputMethodSystemAbility::ShowCurrentInput(uint32_t type) +ErrCode InputMethodSystemAbility::ShowCurrentInput(uint32_t requestId, uint32_t type) { - auto name = ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID()); - auto pid = IPCSkeleton::GetCallingPid(); - auto userId = GetCallingUserId(); - auto imeInfo = GetCurrentImeInfoForHiSysEvent(userId); - auto ret = ShowCurrentInputInner(); - auto evenInfo = HiSysOriginalInfo::Builder() - .SetPeerName(name) - .SetPeerPid(pid) - .SetPeerUserId(userId) - .SetClientType(static_cast(type)) - .SetImeName(imeInfo.second) - .SetEventCode( - static_cast(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_CURRENT_INPUT)) - .SetErrCode(ret) - .Build(); - ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo); - return ret; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + // 1 - generate ShowCurrentInput task + SaActionFunc action = [callerInfo, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return ShowCurrentInputInner(callerInfo); + }; + // 2 - generate HiSysEvent reporter + ReportFunc reporter = [callerInfo, type, this](int32_t ret, const ServiceResponseData &data) { + ReportShowCurrentInput(callerInfo, type, ret); + }; + auto task = + std::make_shared(SaTaskCode::SHOW_CURRENT_INPUT, action, callerInfo, requester->imcResponseChannel); + task->SetHiSysReporter(reporter); + return SaTaskManager::GetInstance().PostTask(task); } -ErrCode InputMethodSystemAbility::ShowInput(const sptr& client, - uint32_t type, int32_t requestKeyboardReason) +ErrCode InputMethodSystemAbility::ShowInput( + uint32_t requestId, const sptr &client, uint32_t type, int32_t requestKeyboardReason) { - auto name = ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID()); - auto pid = IPCSkeleton::GetCallingPid(); - auto userId = GetCallingUserId(); - auto imeInfo = GetCurrentImeInfoForHiSysEvent(userId); - auto ret = ShowInputInner(client, requestKeyboardReason); - auto evenInfo = HiSysOriginalInfo::Builder() - .SetPeerName(name) - .SetPeerPid(pid) - .SetPeerUserId(userId) - .SetClientType(static_cast(type)) - .SetImeName(imeInfo.second) - .SetEventCode(static_cast(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_INPUT)) - .SetErrCode(ret) - .Build(); - ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo); - return ret; + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + // 1 - generate ShowInput task + SaActionFunc action = [this, callerInfo, client, requestKeyboardReason]( + ServiceResponseData &, ActionInnerData &) -> int32_t { + return ShowInputInner(callerInfo, client, requestKeyboardReason); + }; + // 2 - generate HiSysEvent reporter + ReportFunc reporter = [callerInfo, type, this](int32_t ret, const ServiceResponseData &data) { + ReportShowInput(callerInfo, type, ret); + }; + auto task = std::make_shared(SaTaskCode::SHOW_INPUT, action, callerInfo, requester->imcResponseChannel); + task->SetHiSysReporter(reporter); + return SaTaskManager::GetInstance().PostTask(task); } std::pair InputMethodSystemAbility::GetCurrentImeInfoForHiSysEvent(int32_t userId) @@ -2545,16 +2598,16 @@ int32_t InputMethodSystemAbility::GetScreenLockIme(int32_t userId, std::string & int32_t InputMethodSystemAbility::GetAlternativeIme(int32_t userId, std::string &ime) { - InputMethodStatus status = InputMethodStatus::ENABLE; std::vector props; - int32_t ret = ListInputMethod(status, props); + auto ret = ImeInfoInquirer::GetInstance().ListInputMethod( + userId, static_cast(InputMethodStatus::ENABLE), props); if (ret == ErrorCode::NO_ERROR && !props.empty()) { ime = props[0].name + "/" + props[0].id; return ErrorCode::NO_ERROR; } - IMSA_HILOGD("GetListEnableInputMethodIme is failed!"); - status = InputMethodStatus::DISABLE; - ret = ListInputMethod(status, props); + IMSA_HILOGE("GetListEnableInputMethodIme is failed!"); + ret = ImeInfoInquirer::GetInstance().ListInputMethod( + userId, static_cast(InputMethodStatus::DISABLE), props); if (ret != ErrorCode::NO_ERROR || props.empty()) { IMSA_HILOGE("GetListDisableInputMethodIme is failed!"); return ErrorCode::ERROR_NOT_IME; @@ -2568,17 +2621,227 @@ int32_t InputMethodSystemAbility::GetAlternativeIme(int32_t userId, std::string return ErrorCode::ERROR_NOT_IME; } -int32_t InputMethodSystemAbility::SendPrivateData( - const Value &value) +int32_t InputMethodSystemAbility::SendPrivateData(uint32_t requestId, const Value &value) +{ + auto callerInfo = GetCallerInfo(requestId); + auto requester = RequesterManager::GetInstance().GetRequester(callerInfo.pid); + CHECK_NULLPTR_RETURN(requester, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + CHECK_NULLPTR_RETURN(requester->imcResponseChannel, ErrorCode::ERROR_IMSA_REQUESTER_NOT_FOUND); + + SaActionFunc action = [callerInfo, value, this](ServiceResponseData &, ActionInnerData &) -> int32_t { + return SendPrivateDataTask(callerInfo, value); + }; + return SaTaskManager::GetInstance().PostTask( + std::make_shared(SaTaskCode::SEND_PRIVATE_DATA, action, callerInfo, requester->imcResponseChannel)); +} + +InputType InputMethodSystemAbility::GetSecurityInputType(const InputClientInfo &inputClientInfo) +{ + if (inputClientInfo.config.inputAttribute.IsOneTimeCodeFlag()) { + return InputType::ONE_TIME_CODE; + } else if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) { + return InputType::SECURITY_INPUT; + } else { + return InputType::NONE; + } +} + +int32_t InputMethodSystemAbility::StartSecurityIme(const CallerInfo &callerInfo, InputClientInfo &inputClientInfo) +{ + InputType type = GetSecurityInputType(inputClientInfo); + IMSA_HILOGI("InputType:[%{public}d.", type); + if (!InputTypeManager::GetInstance().IsStarted()) { + IMSA_HILOGD("SecurityImeFlag, input type is not started, start."); + // if need to switch ime, no need to hide panel first. + NeedHideWhenSwitchInputType(callerInfo.userId, type, inputClientInfo.needHide); + return StartInputType(callerInfo, type); + } + if (!inputClientInfo.isNotifyInputStart) { + IMSA_HILOGD("SecurityImeFlag, same textField, input type is started, not deal."); + return ErrorCode::NO_ERROR; + } + if (!InputTypeManager::GetInstance().IsInputTypeImeStarted(type)) { + IMSA_HILOGD("SecurityImeFlag, new textField, input type is started, but it is not target, switch."); + NeedHideWhenSwitchInputType(callerInfo.userId, type, inputClientInfo.needHide); + return StartInputType(callerInfo, type); + } + return ErrorCode::NO_ERROR; +} + +void InputMethodSystemAbility::ReportStartInput( + const CallerInfo &callerInfo, const InputClientInfo &clientInfo, const StartInputResponse &response, int32_t ret) +{ + IMSA_HILOGD("HiSysEvent report start!"); + auto evenInfo = HiSysOriginalInfo::Builder() + .SetPeerName(ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID())) + .SetPeerPid(callerInfo.pid) + .SetPeerUserId(callerInfo.userId) + .SetClientType(clientInfo.type) + .SetInputPattern(clientInfo.attribute.inputPattern) + .SetIsShowKeyboard(clientInfo.isShowKeyboard) + .SetImeName(response.bundleName) + .SetErrCode(ret) + .Build(); + ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_ATTACH, *evenInfo); + IMSA_HILOGD("HiSysEvent report end!"); +} + +void InputMethodSystemAbility::ReportShowCurrentInput(const CallerInfo &info, uint32_t type, int32_t ret) +{ + IMSA_HILOGD("HiSysEvent report start!"); + auto name = ImfHiSysEventUtil::GetAppName(info.tokenId); + auto pid = IPCSkeleton::GetCallingPid(); + auto userId = GetCallingUserId(); + auto imeInfo = GetCurrentImeInfoForHiSysEvent(userId); + auto evenInfo = + HiSysOriginalInfo::Builder() + .SetPeerName(name) + .SetPeerPid(pid) + .SetPeerUserId(userId) + .SetClientType(static_cast(type)) + .SetImeName(imeInfo.second) + .SetEventCode(static_cast(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_CURRENT_INPUT)) + .SetErrCode(ret) + .Build(); + ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo); + IMSA_HILOGE("HiSysEvent report end!"); +} + +void InputMethodSystemAbility::ReportShowInput(const CallerInfo &info, uint32_t type, int32_t ret) +{ + IMSA_HILOGD("HiSysEvent report start!"); + auto name = ImfHiSysEventUtil::GetAppName(info.tokenId); + auto imeInfo = GetCurrentImeInfoForHiSysEvent(info.userId); + auto evenInfo = HiSysOriginalInfo::Builder() + .SetPeerName(name) + .SetPeerPid(info.pid) + .SetPeerUserId(info.userId) + .SetClientType(static_cast(type)) + .SetImeName(imeInfo.second) + .SetEventCode(static_cast(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_INPUT)) + .SetErrCode(ret) + .Build(); + ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo); + IMSA_HILOGE("HiSysEvent report end!"); +} + +int32_t InputMethodSystemAbility::HideCurrentInputTask(const CallerInfo &callerInfo) +{ + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + if (identityChecker_->IsBroker(callerInfo.tokenId)) { + return session->OnHideCurrentInput(GetCallingDisplayId(callerInfo.pid)); + } + if (!identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { + return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; + } + return session->OnHideCurrentInput(GetCallingDisplayId(callerInfo.pid)); +} + +int32_t InputMethodSystemAbility::UnRegisteredProxyImeTask( + const CallerInfo &callerInfo, int32_t type, const sptr &core) +{ + if (!identityChecker_->IsNativeSa(callerInfo.tokenId)) { + IMSA_HILOGE("not native sa!"); + return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; + } + std::shared_ptr session = nullptr; + GET_USER_SESSION(callerInfo.userId, session, ErrorCode::ERROR_NULL_POINTER); + // 1 - restore ime + auto doRestoreIme = [this, type, callerInfo, session](ServiceResponseData &, ActionInnerData &) -> int32_t { + if (static_cast(type) != UnRegisteredType::SWITCH_PROXY_IME_TO_IME) { + return ErrorCode::NO_ERROR; + } + if (session->CheckSecurityMode()) { + return StartInputType(callerInfo, InputType::SECURITY_INPUT); + } else { + return session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); + } + }; + // 2 - remove proxy ime data + auto doUnregister = [session, type, core](ServiceResponseData &, ActionInnerData &) -> int32_t { + return session->OnUnRegisteredProxyIme(static_cast(type), core); + }; + return SaTaskManager::GetInstance().Pend(doRestoreIme, doUnregister); +} + +int32_t InputMethodSystemAbility::PanelStatusChangeTask( + const CallerInfo &callerInfo, uint32_t status, const ImeWindowInfo &info) +{ + if (!IsCurrentIme(callerInfo.userId)) { + IMSA_HILOGE("not current ime!"); + return ErrorCode::ERROR_NOT_CURRENT_IME; + } + auto ret = ImCommonEventManager::GetInstance().PublishPanelStatusChangeEvent( + callerInfo.userId, static_cast(status), info); + IMSA_HILOGD("public panel status change event: %{public}d", ret); + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnPanelStatusChange( + static_cast(status), info, GetCallingDisplayId(callerInfo.pid)); +} + +int32_t InputMethodSystemAbility::UpdateListenEventFlagTask( + const CallerInfo &callerInfo, const InputClientInfoInner &clientInfoInner, uint32_t eventFlag) +{ + InputClientInfo clientInfo = InputMethodTools::GetInstance().InnerToInputClientInfo(clientInfoInner); + IMSA_HILOGD("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag); + if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag) + || EventStatusManager::IsInputStatusChangedOn(eventFlag)) { + if (!identityChecker_->IsSystemApp(callerInfo.fullTokenId) + && !identityChecker_->IsNativeSa(callerInfo.tokenId)) { + IMSA_HILOGE("not system application!"); + return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; + } + } + auto ret = GenerateClientInfo(callerInfo, const_cast(clientInfo)); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnUpdateListenEventFlag(clientInfo); +} + +int32_t InputMethodSystemAbility::SetCallingWindowTask( + const CallerInfo &callerInfo, uint32_t windowId, const sptr &client) +{ + IMSA_HILOGD("IMF SA setCallingWindow enter"); + if (identityChecker_ == nullptr) { + return ErrorCode::ERROR_NULL_POINTER; + } + if (!identityChecker_->IsBroker(callerInfo.tokenId) + && !identityChecker_->IsFocused(callerInfo.pid, callerInfo.tokenId)) { + return ErrorCode::ERROR_CLIENT_NOT_FOCUSED; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + auto callingDisplayId = identityChecker_->GetDisplayIdByWindowId(windowId); + return session->OnSetCallingWindow(windowId, callingDisplayId, client); +} + +int32_t InputMethodSystemAbility::SendPrivateDataTask(const CallerInfo &callerInfo, const Value &value) { std::unordered_map privateCommand; privateCommand = value.valueMap; if (privateCommand.empty()) { - IMSA_HILOGE("privateCommand is empty!"); + IMSA_HILOGE("PrivateCommand is empty!"); return ErrorCode::ERROR_PRIVATE_COMMAND_IS_EMPTY; } - if (!identityChecker_->IsSpecialSaUid()) { - IMSA_HILOGE("uid failed, not permission!"); + if (!identityChecker_->IsSpecialSaUid(callerInfo.uid)) { + IMSA_HILOGE("Uid failed, not permission!"); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } auto session = UserSessionManager::GetInstance().GetUserSession(userId_); @@ -2597,37 +2860,141 @@ int32_t InputMethodSystemAbility::SendPrivateData( return ret; } -InputType InputMethodSystemAbility::GetSecurityInputType(const InputClientInfo &inputClientInfo) +int32_t InputMethodSystemAbility::IsCurrentImeByPidTask(const CallerInfo &callerInfo, int32_t pid, bool &resultValue) { - if (inputClientInfo.config.inputAttribute.IsOneTimeCodeFlag()) { - return InputType::ONE_TIME_CODE; - } else if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) { - return InputType::SECURITY_INPUT; - } else { - return InputType::NONE; + if (!identityChecker_->IsSystemApp(callerInfo.fullTokenId) && !identityChecker_->IsNativeSa(callerInfo.tokenId)) { + IMSA_HILOGE("not system application or system ability!"); + resultValue = false; + return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + resultValue = false; + return ErrorCode::ERROR_NULL_POINTER; } + resultValue = session->IsCurrentImeByPid(pid); + return ERR_OK; } -int32_t InputMethodSystemAbility::StartSecurityIme(int32_t &userId, InputClientInfo &inputClientInfo) +int32_t InputMethodSystemAbility::ExitCurrentInputTypeTask(const CallerInfo &callerInfo) { - InputType type = GetSecurityInputType(inputClientInfo); - IMSA_HILOGI("InputType:[%{public}d.", type); - if (!InputTypeManager::GetInstance().IsStarted()) { - IMSA_HILOGD("SecurityImeFlag, input type is not started, start."); - // if need to switch ime, no need to hide panel first. - NeedHideWhenSwitchInputType(userId, type, inputClientInfo.needHide); - return StartInputType(userId, type); + auto userId = callerInfo.userId; + auto ret = IsDefaultImeFromTokenId(userId, callerInfo.tokenId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("not default ime!"); + return ErrorCode::ERROR_NOT_DEFAULT_IME; } - if (!inputClientInfo.isNotifyInputStart) { - IMSA_HILOGD("SecurityImeFlag, same textField, input type is started, not deal."); - return ErrorCode::NO_ERROR; + auto session = UserSessionManager::GetInstance().GetUserSession(userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", userId); + return ErrorCode::ERROR_NULL_POINTER; } - if (!InputTypeManager::GetInstance().IsInputTypeImeStarted(type)) { - IMSA_HILOGD("SecurityImeFlag, new textField, input type is started, but it is not target, switch."); - NeedHideWhenSwitchInputType(userId, type, inputClientInfo.needHide); - return StartInputType(userId, type); + if (session->CheckSecurityMode()) { + return StartInputType(callerInfo, InputType::SECURITY_INPUT); + } + auto typeIme = InputTypeManager::GetInstance().GetCurrentIme(); + auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId); + if (cfgIme->bundleName == typeIme.bundleName) { + return session->RestoreCurrentImeSubType(DEFAULT_DISPLAY_ID); + } + return session->RestoreCurrentIme(DEFAULT_DISPLAY_ID); +} + +int32_t InputMethodSystemAbility::GetSecurityModeTask(const CallerInfo &callerInfo, int32_t &security) +{ + IMSA_HILOGD("InputMethodSystemAbility start."); + auto userId = callerInfo.userId; + auto bundleName = FullImeInfoManager::GetInstance().Get(userId, callerInfo.tokenId); + if (bundleName.empty()) { + bundleName = identityChecker_->GetBundleNameByToken(callerInfo.tokenId); + if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) { + IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str()); + return ErrorCode::ERROR_NOT_IME; + } + } + security = static_cast(SecurityMode::BASIC); + EnabledStatus status = EnabledStatus::BASIC_MODE; + auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, status); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGW("[%{public}d, %{public}s] get enabled status failed:%{public}d,!", userId, bundleName.c_str(), ret); } + if (status == EnabledStatus::FULL_EXPERIENCE_MODE) { + security = static_cast(SecurityMode::FULL); + } + return ErrorCode::NO_ERROR; +} + +int32_t InputMethodSystemAbility::ConnectSystemCmdTask( + const CallerInfo &callerInfo, const sptr &channel, sptr &agent) +{ + if (!identityChecker_->HasPermission(callerInfo.tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) { + IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!"); + return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnConnectSystemCmd(channel, agent); +} + +int32_t InputMethodSystemAbility::GetInputMethodStateTask(const CallerInfo &callerInfo, int32_t &status) +{ + auto userId = callerInfo.userId; + auto bundleName = FullImeInfoManager::GetInstance().Get(userId, callerInfo.tokenId); + if (bundleName.empty()) { + bundleName = identityChecker_->GetBundleNameByToken(callerInfo.tokenId); + if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) { + IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str()); + return ErrorCode::ERROR_NOT_IME; + } + } + EnabledStatus tmpStatus = EnabledStatus::DISABLED; + auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, tmpStatus); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + status = static_cast(tmpStatus); return ErrorCode::NO_ERROR; } + +int32_t InputMethodSystemAbility::RegisterProxyImeTask(const CallerInfo &callerInfo, uint64_t displayId, + const sptr &core, const sptr &agent) +{ + if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) { + IMSA_HILOGE("current device does not support app agent"); + return ErrorCode::ERROR_DEVICE_UNSUPPORTED; + } + if (!identityChecker_->IsValidVirtualIme(callerInfo.uid)) { + IMSA_HILOGE("not agent sa"); + return ErrorCode::ERROR_NOT_AI_APP_IME; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnRegisterProxyIme(callerInfo, displayId, core, agent); +} + +int32_t InputMethodSystemAbility::UnregisterProxyImeTask(const CallerInfo &callerInfo, uint64_t displayId) +{ + if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) { + IMSA_HILOGE("current device does not support app agent"); + return ErrorCode::ERROR_DEVICE_UNSUPPORTED; + } + if (!identityChecker_->IsValidVirtualIme(callerInfo.uid)) { + IMSA_HILOGE("not agent sa"); + return ErrorCode::ERROR_NOT_AI_APP_IME; + } + auto session = UserSessionManager::GetInstance().GetUserSession(callerInfo.userId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callerInfo.userId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnUnregisterProxyIme(displayId); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 8a5264bfdb77e35c0e1dac7a2795b1363330a33e..1bbe311fbec1e309d957ae02a7021f3ec62e206c 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -13,8 +13,6 @@ * limitations under the License. */ -#include "unordered_map" -#include "variant" #include "peruser_session.h" #include @@ -26,31 +24,30 @@ #include "ime_connection.h" #include "ime_enabled_info_manager.h" #include "ime_info_inquirer.h" +#include "ime_state_manager_factory.h" #include "input_control_channel_service_impl.h" +#include "input_method_tools.h" +#include "inputmethod_trace.h" #include "ipc_skeleton.h" #include "iservice_registry.h" #include "mem_mgr_client.h" #include "numkey_apps_manager.h" #include "on_demand_start_stop_sa.h" #include "os_account_adapter.h" +#include "sa_task_manager.h" #include "scene_board_judgement.h" #include "system_ability_definition.h" +#include "unordered_map" +#include "variant_util.h" +#include "window_adapter.h" #include "wms_connection_observer.h" -#include "dm_common.h" -#include "display_manager.h" -#include "parameters.h" #ifdef IMF_SCREENLOCK_MGR_ENABLE #include "screenlock_manager.h" #endif -#include "window_adapter.h" -#include "input_method_tools.h" -#include "ime_state_manager_factory.h" -#include "inputmethod_trace.h" namespace OHOS { namespace MiscServices { using namespace std::chrono; -using namespace MessageID; using namespace OHOS::AppExecFwk; using namespace OHOS::Rosen; constexpr uint32_t STOP_IME_TIME = 600; @@ -62,10 +59,7 @@ constexpr int32_t MAX_RESTART_NUM = 3; constexpr int32_t IME_RESET_TIME_OUT = 3; constexpr int32_t MAX_RESTART_TASKS = 2; constexpr const char *UNDEFINED = "undefined"; -PerUserSession::PerUserSession(int userId) : userId_(userId) { } - -PerUserSession::PerUserSession(int32_t userId, const std::shared_ptr &eventHandler) - : userId_(userId), eventHandler_(eventHandler) +PerUserSession::PerUserSession(int32_t userId) : userId_(userId) { // if bms not start, AppMgrClient::GetProcessRunningInfosByUserId will blocked if (IsSaReady(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID)) { @@ -78,8 +72,8 @@ PerUserSession::PerUserSession(int32_t userId, const std::shared_ptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event) +int PerUserSession::AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, + ClientAddEvent event) { IMSA_HILOGD("PerUserSession start."); auto clientGroup = GetClientGroup(clientInfo.displayId); @@ -194,11 +188,21 @@ void PerUserSession::OnClientDied(sptr remote) clientGroup->RemoveClientInfo(remote->AsObject(), true); } -/** Handle the situation that an ime died - * It's called when an ime died - * @param the remote object handler of the ime who died. - */ -void PerUserSession::OnImeDied(const sptr &remote, ImeType type) +void PerUserSession::OnImeDied( + const sptr &remote, ImeType type, const std::string &bundleName, pid_t pid) +{ + std::weak_ptr weakThis = shared_from_this(); + auto func = [weakThis, remote, type, bundleName, pid](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + sharedThis->OnImeDiedInner(remote, type, bundleName, pid); + return ErrorCode::NO_ERROR; + }; + SaTaskManager::GetInstance().PostTask(std::make_shared(SaTaskCode::ON_IME_DIED, func)); +} + +void PerUserSession::OnImeDiedInner( + const sptr &remote, ImeType type, const std::string &bundleName, pid_t pid) { if (remote == nullptr) { return; @@ -208,7 +212,7 @@ void PerUserSession::OnImeDied(const sptr &remote, ImeType typ if (imeData != nullptr && imeData->imeStatus == ImeStatus::EXITING) { RemoveImeData(type, true); InputTypeManager::GetInstance().Set(false); - NotifyImeStopFinished(); + NotifyImeStopFinished(bundleName); IMSA_HILOGI("%{public}d not current imeData.", type); return; } @@ -518,74 +522,128 @@ bool PerUserSession::IsProxyImeEnable() return ret; } -int32_t PerUserSession::OnStartInput( - const InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo) +int32_t PerUserSession::GetBindClientInfo(const InputClientInfo &inputInfo, InputClientInfo &outputInfo) { - const sptr &client = inputClientInfo.client; + const sptr &client = inputInfo.client; if (client == nullptr) { IMSA_HILOGE("client is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - auto clientGroup = GetClientGroup(inputClientInfo.displayId); + auto clientGroup = GetClientGroup(inputInfo.displayId); if (clientGroup == nullptr) { IMSA_HILOGE("client group not found"); return ErrorCode::ERROR_CLIENT_NOT_FOUND; } - auto clientInfo = clientGroup->GetClientInfo(client->AsObject()); + std::shared_ptr clientInfo = clientGroup->GetClientInfo(client->AsObject()); if (clientInfo == nullptr) { return ErrorCode::ERROR_CLIENT_NOT_FOUND; } - IMSA_HILOGD("start input with keyboard[%{public}d].", inputClientInfo.isShowKeyboard); - InputClientInfo infoTemp = *clientInfo; - infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart; - ImeType imeType = GetImeType(inputClientInfo.displayId); - if (GetDisplayGroupId(inputClientInfo.displayId) == DEFAULT_DISPLAY_ID) { - HandleImeBindTypeChanged(infoTemp, clientGroup); - imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME; - } - infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard; - infoTemp.needHide = inputClientInfo.needHide; - infoTemp.requestKeyboardReason = inputClientInfo.requestKeyboardReason; - infoTemp.config.requestKeyboardReason = inputClientInfo.requestKeyboardReason; - if (inputClientInfo.config.inputAttribute.IsSecurityImeFlag()) { - infoTemp.config.isSimpleKeyboardEnabled = false; - } else { - infoTemp.config.isSimpleKeyboardEnabled = inputClientInfo.config.isSimpleKeyboardEnabled; - } - int32_t ret = - BindClientWithIme(std::make_shared(infoTemp), imeType, true, inputClientInfo.displayId); + outputInfo = *clientInfo; + outputInfo.UpdateInfoAboutBind(inputInfo); + return ErrorCode::NO_ERROR; +} + +int32_t PerUserSession::OnStartInput(const InputClientInfo &info) +{ + // get bind client info + InputClientInfo infoTemp; + auto ret = GetBindClientInfo(info, infoTemp); if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("bind failed, ret: %{public}d!", ret); return ret; } - auto data = GetReadyImeData(imeType); - if (data == nullptr || data->agent == nullptr) { - IMSA_HILOGE("data or agent is nullptr!"); - return ErrorCode::ERROR_IME_NOT_STARTED; + + // get bind ime type + auto imeType = GetImeType(info.displayId); + if (GetDisplayGroupId(info.displayId) == DEFAULT_DISPLAY_ID) { + HandleImeBindTypeChanged(infoTemp); + imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME; } - agent = data->agent; - imeInfo = { data->pid, data->ime.first }; - return ErrorCode::NO_ERROR; + + // 1 - generate BindClientWithIme action + std::weak_ptr weakThis = shared_from_this(); + auto bindFunc = [weakThis, infoTemp, imeType, info](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + IMSA_HILOGD("start input with keyboard[%{public}d].", info.isShowKeyboard); + return sharedThis->BindClientWithIme( + std::make_shared(infoTemp), imeType, true, info.displayId, true); + }; + auto onFailed = [](int32_t ret) { IMSA_HILOGE("bind failed, ret: %{public}d!", ret); }; + auto bindAction = std::make_unique(bindFunc, nullptr, onFailed); + + // 2 - generate action to SetResponseData + auto setResponse = [weakThis, imeType](ServiceResponseData &data, ActionInnerData &) { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + auto imeData = sharedThis->GetReadyImeData(imeType); + if (imeData == nullptr || imeData->agent == nullptr) { + IMSA_HILOGE("data or agent is nullptr!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + StartInputResponse response; + response.Set(imeData->agent, imeData->pid, imeData->ime.first); + data = response; + return ErrorCode::NO_ERROR; + }; + + // 3 - pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(bindAction), setResponse); } -int32_t PerUserSession::BindClientWithIme( - const std::shared_ptr &clientInfo, ImeType type, bool isBindFromClient, uint64_t displayId) +int32_t PerUserSession::BindClientWithIme(const std::shared_ptr &clientInfo, ImeType type, + bool isBindFromClient, uint64_t displayId, bool mustStartIme) { if (clientInfo == nullptr) { IMSA_HILOGE("clientInfo is nullptr!"); return ErrorCode::ERROR_IMSA_NULLPTR; } - auto clientGroup = GetClientGroup(displayId); - if (clientGroup == nullptr) { + auto group = GetClientGroup(displayId); + if (group == nullptr) { IMSA_HILOGE("not found group"); return ErrorCode::ERROR_IMSA_NULLPTR; } - IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type, - clientInfo->isShowKeyboard, isBindFromClient); - auto data = GetValidIme(type); - if (data == nullptr) { + // Only try GetValidIme when binding IME with mustStartIme true. + auto imeData = GetReadyImeData(type); + if (imeData == nullptr && (!mustStartIme || type != ImeType::IME)) { + IMSA_HILOGE("no valid ime data, type: %{public}d", type); return ErrorCode::ERROR_IME_NOT_STARTED; } + + // 1 - generate PrepareValidIme action + std::weak_ptr weakThis = shared_from_this(); + auto doGet = [weakThis, type](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->PrepareValidIme(type); + }; + auto onGetFail = [](int32_t) { IMSA_HILOGE("failed to get valid ime data"); }; + auto getAction = std::make_unique(doGet, nullptr, onGetFail, true, ErrorCode::ERROR_IME_NOT_STARTED); + + // 2 - generate StartImeInput action + auto doStartInput = [weakThis, type, group, info = *clientInfo, isBindFromClient]( + ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + auto ret = sharedThis->StartImeInput(type, info, isBindFromClient); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + return sharedThis->OnBindFinished(group, info, type); + }; + + // 3 - pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(getAction), doStartInput); +} + +int32_t PerUserSession::StartImeInput(ImeType type, const InputClientInfo &clientInfo, bool isBindFromClient) +{ + auto data = GetReadyImeData(type); + if (data == nullptr || data->core == nullptr) { + IMSA_HILOGE("imeData or core nullptr"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type, + clientInfo.isShowKeyboard, isBindFromClient); if (!data->imeExtendInfo.privateCommand.empty()) { auto ret = SendPrivateData(data->imeExtendInfo.privateCommand); if (ret != ErrorCode::NO_ERROR) { @@ -593,34 +651,43 @@ int32_t PerUserSession::BindClientWithIme( return ret; } } - auto ret = RequestIme(data, RequestType::START_INPUT, - [&data, &clientInfo, isBindFromClient]() { - InputClientInfoInner inputClientInfoInner = - InputMethodTools::GetInstance().InputClientInfoToInner(const_cast(*clientInfo)); - return data->core->StartInput(inputClientInfoInner, isBindFromClient); + auto ret = RequestIme(data, RequestType::START_INPUT, [&data, &clientInfo, isBindFromClient]() { + InputClientInfoInner inputClientInfoInner = InputMethodTools::GetInstance().InputClientInfoToInner(clientInfo); + return data->core->StartInput(inputClientInfoInner, isBindFromClient); }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("start input failed, ret: %{public}d!", ret); return ErrorCode::ERROR_IME_START_INPUT_FAILED; } if (type == ImeType::IME) { - InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid, - ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); + InputMethodSysEvent::GetInstance().ReportImeState( + ImeState::BIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID); } if (!isBindFromClient) { - ret = clientInfo->client->OnInputReady(data->agent, data->pid, data->ime.first); + ret = clientInfo.client->OnInputReady(data->agent, data->pid, data->ime.first); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("start client input failed, ret: %{public}d!", ret); return ErrorCode::ERROR_IMSA_CLIENT_INPUT_READY_FAILED; } } - clientGroup->UpdateClientInfo(clientInfo->client->AsObject(), { { UpdateFlag::BINDIMETYPE, type }, - { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard }, { UpdateFlag::STATE, ClientState::ACTIVE } }); - ReplaceCurrentClient(clientInfo->client, clientGroup); - if (clientInfo->isShowKeyboard) { + return ErrorCode::NO_ERROR; +} + +int32_t PerUserSession::OnBindFinished( + const std::shared_ptr &clientGroup, const InputClientInfo &clientInfo, ImeType type) +{ + if (clientGroup == nullptr) { + IMSA_HILOGE("clientGroup is nullptr"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + clientGroup->UpdateClientInfo(clientInfo.client->AsObject(), + { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo.isShowKeyboard }, + { UpdateFlag::STATE, ClientState::ACTIVE } }); + ReplaceCurrentClient(clientInfo.client, clientGroup); + if (clientInfo.isShowKeyboard) { clientGroup->NotifyInputStartToClients( - clientInfo->config.windowId, static_cast(clientInfo->requestKeyboardReason)); + clientInfo.config.windowId, static_cast(clientInfo.requestKeyboardReason)); } return ErrorCode::NO_ERROR; } @@ -686,10 +753,11 @@ void PerUserSession::OnSecurityChange(int32_t security) IMSA_HILOGD("on security change, ret: %{public}d.", ret); } -int32_t PerUserSession::OnSetCoreAndAgent(const sptr &core, const sptr &agent) +int32_t PerUserSession::OnSetCoreAndAgent( + const CallerInfo &callerInfo, const sptr &core, const sptr &agent) { IMSA_HILOGI("start."); - auto ret = UpdateImeData(core, agent, IPCSkeleton::GetCallingPid()); + auto ret = UpdateImeData(core, agent, callerInfo.pid); if (ret != ErrorCode::NO_ERROR) { return ret; } @@ -709,16 +777,16 @@ int32_t PerUserSession::OnSetCoreAndAgent(const sptr &core, co BindClientWithIme(clientInfo, imeType); SetInputType(); } - bool isStarted = true; - isImeStarted_.SetValue(isStarted); + NotifyImeStartReady(callerInfo); return ErrorCode::NO_ERROR; } -int32_t PerUserSession::OnRegisterProxyIme(const sptr &core, const sptr &agent) +int32_t PerUserSession::OnRegisterProxyIme( + const CallerInfo &callerInfo, const sptr &core, const sptr &agent) { IMSA_HILOGD("start."); auto imeType = ImeType::PROXY_IME; - auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid()); + auto ret = AddImeData(imeType, core, agent, callerInfo.pid); if (ret != ErrorCode::NO_ERROR) { return ret; } @@ -735,12 +803,12 @@ int32_t PerUserSession::OnRegisterProxyIme(const sptr &core, c return ErrorCode::NO_ERROR; } -int32_t PerUserSession::OnRegisterProxyIme( - uint64_t displayId, const sptr &core, const sptr &agent) +int32_t PerUserSession::OnRegisterProxyIme(const CallerInfo &callerInfo, uint64_t displayId, + const sptr &core, const sptr &agent) { IMSA_HILOGI("start. displayId: %{public}" PRIu64 "", displayId); auto imeType = ImeType::PROXY_AGENT_IME; - auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid()); + auto ret = AddImeData(imeType, core, agent, callerInfo.pid); if (ret != ErrorCode::NO_ERROR) { return ret; } @@ -857,7 +925,6 @@ void PerUserSession::StartImeIfInstalled() void PerUserSession::ReplaceCurrentClient( const sptr &client, const std::shared_ptr &clientGroup) { - std::lock_guard lock(focusedClientLock_); if (client == nullptr || clientGroup == nullptr) { return; } @@ -907,7 +974,8 @@ int32_t PerUserSession::AddImeData(ImeType type, sptr core, sp IMSA_HILOGE("failed to new deathRecipient!"); return ErrorCode::ERROR_NULL_POINTER; } - deathRecipient->SetDeathRecipient([this, core, type](const wptr &) { this->OnImeDied(core, type); }); + deathRecipient->SetDeathRecipient( + [this, core, type, pid](const wptr &) { this->OnImeDied(core, type, "proxyIme", pid); }); auto coreObject = core->AsObject(); if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) { IMSA_HILOGE("failed to add death recipient!"); @@ -943,15 +1011,32 @@ std::shared_ptr PerUserSession::GetReadyImeData(ImeType type) return it->second; } -std::shared_ptr PerUserSession::GetValidIme(ImeType type) +int32_t PerUserSession::PrepareValidIme(ImeType type) { auto data = GetReadyImeData(type); if (data != nullptr || type != ImeType::IME) { - return data; + return ErrorCode::NO_ERROR; } - IMSA_HILOGI("current ime is empty, try to restart it."); - StartCurrentIme(); - return GetReadyImeData(type); + // 1 - generate StartCurrentIme action + std::weak_ptr weakThis = shared_from_this(); + auto doStartIme = [weakThis](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->StartCurrentIme(); + }; + auto startAction = std::make_unique(doStartIme, nullptr, nullptr, false); + // 2 - generate GetReadyIme action + auto checkImeValid = [weakThis, type](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + auto data = sharedThis->GetReadyImeData(type); + if (data != nullptr) { + return ErrorCode::NO_ERROR; + } + return ErrorCode::ERROR_IME_NOT_STARTED; + }; + // 3 - pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(startAction), checkImeValid); } void PerUserSession::RemoveImeData(ImeType type, bool isImeDied) @@ -971,7 +1056,6 @@ void PerUserSession::RemoveImeData(ImeType type, bool isImeDied) void PerUserSession::OnFocused(uint64_t displayId, int32_t pid, int32_t uid) { - std::lock_guard lock(focusedClientLock_); auto clientGroup = GetClientGroup(displayId); if (clientGroup == nullptr) { return; @@ -1036,7 +1120,6 @@ void PerUserSession::OnScreenUnlock() #endif } - std::shared_ptr PerUserSession::GetCurrentClientInfo(uint64_t displayId) { auto clientGroup = GetClientGroup(displayId); @@ -1076,46 +1159,64 @@ int32_t PerUserSession::StartCurrentIme(bool isStopCurrentIme) IMSA_HILOGE("imeToStart is nullptr!"); return ErrorCode::ERROR_IMSA_IME_TO_START_NULLPTR; } - auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_); - IMSA_HILOGD("currentIme: %{public}s, imeToStart: %{public}s.", currentIme->imeId.c_str(), - imeToStart->imeId.c_str()); - auto ret = StartIme(imeToStart, isStopCurrentIme); - if (ret != ErrorCode::NO_ERROR) { + + // 1 - generate start action + std::weak_ptr weakThis = shared_from_this(); + auto doStart = [weakThis, imeToStart, isStopCurrentIme](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + auto curIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(sharedThis->userId_); + IMSA_HILOGD( + "currentIme: %{public}s, imeToStart: %{public}s.", curIme->imeId.c_str(), imeToStart->imeId.c_str()); + return sharedThis->StartIme(imeToStart, isStopCurrentIme); + }; + auto onStartFail = [imeId = imeToStart->imeId](int32_t ret) { IMSA_HILOGE("failed to start ime!"); - InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, - imeToStart->imeId, "start ime failed!"); - return ret; - } + InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, imeId, "start ime failed!"); + }; + auto doStartAction = std::make_unique(doStart, nullptr, onStartFail); + + // 2 - generate action after StartIme + auto afterStart = [weakThis, subName = imeToStart->subName](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->NotifyAfterStartCurrentIme(subName.empty()); + }; + + // pend above two actions + return SaTaskManager::GetInstance().Pend(std::move(doStartAction), afterStart); +} + +int32_t PerUserSession::NotifyAfterStartCurrentIme(bool isSubNameUndefined) +{ auto readyIme = GetReadyImeData(ImeType::IME); if (readyIme == nullptr) { IMSA_HILOGE("ime abnormal."); return ErrorCode::ERROR_IME_NOT_STARTED; } IMSA_HILOGI("current ime changed to %{public}s.", readyIme->ime.first.c_str()); - currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_); - if (currentIme == nullptr) { - IMSA_HILOGW("currentIme not find."); + auto ime = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_); + if (ime == nullptr) { + IMSA_HILOGW("currentIme not found."); return ErrorCode::NO_ERROR; } - if (readyIme->ime.first != currentIme->bundleName) { - IMSA_HILOGI("ime:%{public}s not user set default ime: %{public}s, no need to notify.", - readyIme->ime.first.c_str(), currentIme->bundleName.c_str()); + if (readyIme->ime.first != ime->bundleName) { + IMSA_HILOGI("%{public}s not set default by user: %{public}s, no need to notify.", readyIme->ime.first.c_str(), + ime->bundleName.c_str()); return ErrorCode::NO_ERROR; } - auto currentImeInfo = - ImeInfoInquirer::GetInstance().GetImeInfo(userId_, currentIme->bundleName, currentIme->subName); - if (currentImeInfo == nullptr) { + auto imeInfo = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, ime->bundleName, ime->subName); + if (imeInfo == nullptr) { IMSA_HILOGD("currentImeInfo is nullptr!"); return ErrorCode::NO_ERROR; } - NotifyImeChangeToClients(currentImeInfo->prop, currentImeInfo->subProp); - if (imeToStart->subName.empty()) { + NotifyImeChangeToClients(imeInfo->prop, imeInfo->subProp); + if (isSubNameUndefined) { IMSA_HILOGW("undefined subtype"); - currentImeInfo->subProp.id = UNDEFINED; - currentImeInfo->subProp.name = UNDEFINED; + imeInfo->subProp.id = UNDEFINED; + imeInfo->subProp.name = UNDEFINED; } - - ret = SwitchSubtypeWithoutStartIme(currentImeInfo->subProp); + auto ret = SwitchSubtypeWithoutStartIme(imeInfo->subProp); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("SwitchSubtype failed!"); } @@ -1212,7 +1313,18 @@ int32_t PerUserSession::StartInputService(const std::shared_ptr &i return ret; } InitImeData({ imeToStart->bundleName, imeToStart->extName }, ime); - isImeStarted_.Clear(false); + ret = StartImeExtAbility(imeToStart); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + return WaitForImeStart(imeToStart); +} + +int32_t PerUserSession::StartImeExtAbility(const std::shared_ptr &imeToStart) +{ + if (imeToStart == nullptr) { + return ErrorCode::ERROR_IMSA_IME_TO_START_NULLPTR; + } sptr connection = new (std::nothrow) ImeConnection(); if (connection == nullptr) { IMSA_HILOGE("failed to create connection!"); @@ -1220,22 +1332,30 @@ int32_t PerUserSession::StartInputService(const std::shared_ptr &i } auto want = GetWant(imeToStart); IMSA_HILOGI("connect %{public}s start!", imeToStart->imeId.c_str()); - ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectExtensionAbility(want, connection, userId_); + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectExtensionAbility(want, connection, userId_); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("connect %{public}s failed, ret: %{public}d!", imeToStart->imeId.c_str(), ret); InputMethodSysEvent::GetInstance().InputmethodFaultReporter( ErrorCode::ERROR_IMSA_IME_CONNECT_FAILED, imeToStart->imeId, "failed to start ability."); return ErrorCode::ERROR_IMSA_IME_CONNECT_FAILED; } - if (!isImeStarted_.GetValue()) { - IMSA_HILOGE("start %{public}s timeout!", imeToStart->imeId.c_str()); - return ErrorCode::ERROR_IMSA_IME_START_TIMEOUT; - } - IMSA_HILOGI("%{public}s started successfully.", imeToStart->imeId.c_str()); - InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME); return ErrorCode::NO_ERROR; } +int32_t PerUserSession::StopImeExtAbility(const std::string &bundleName, const std::string &extName) +{ + AAFwk::Want want; + want.SetElementName(bundleName, extName); + auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility( + want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("StopExtensionAbility [%{public}s, %{public}s] failed, ret: %{public}d!", bundleName.c_str(), + extName.c_str(), ret); + return ErrorCode::ERROR_IMSA_IME_DISCONNECT_FAILED; + } + return ret; +} + int64_t PerUserSession::GetCurrentClientPid(uint64_t displayId) { auto clientGroup = GetClientGroup(displayId); @@ -1334,17 +1454,16 @@ int32_t PerUserSession::OnSetCallingWindow(uint32_t callingWindowId, return ErrorCode::NO_ERROR; } -int32_t PerUserSession::GetInputStartInfo( - uint64_t displayId, bool &isInputStart, uint32_t &callingWndId, int32_t &requestKeyboardReason) +int32_t PerUserSession::GetInputStartInfo(uint64_t displayId, InputStartInfo &inputStartInfo) { auto clientInfo = GetCurrentClientInfo(displayId); if (clientInfo == nullptr) { IMSA_HILOGE("nullptr clientInfo!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } - isInputStart = true; - callingWndId = clientInfo->config.windowId; - requestKeyboardReason = static_cast(clientInfo->requestKeyboardReason); + inputStartInfo.isInputStart = true; + inputStartInfo.callingWindowId = clientInfo->config.windowId; + inputStartInfo.requestKeyboardReason = static_cast(clientInfo->requestKeyboardReason); return ErrorCode::NO_ERROR; } @@ -1369,16 +1488,6 @@ bool PerUserSession::IsImeBindTypeChanged(ImeType bindImeType) (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable()); } -int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty) -{ - auto data = GetValidIme(ImeType::IME); - if (data == nullptr) { - IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); - return ErrorCode::ERROR_IME_NOT_STARTED; - } - return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { return data->core->SetSubtype(subProperty); }); -} - int32_t PerUserSession::SwitchSubtypeWithoutStartIme(const SubProperty &subProperty) { auto data = GetReadyImeData(ImeType::IME); @@ -1393,7 +1502,7 @@ int32_t PerUserSession::SwitchSubtypeWithoutStartIme(const SubProperty &subPrope int32_t PerUserSession::SetInputType() { InputType inputType = InputTypeManager::GetInstance().GetCurrentInputType(); - auto data = GetValidIme(ImeType::IME); + auto data = GetReadyImeData(ImeType::IME); if (data == nullptr) { IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; @@ -1445,7 +1554,7 @@ int32_t PerUserSession::RestoreCurrentImeSubType(uint64_t callingDisplayId) subProp = *subPropTemp; } IMSA_HILOGD("same ime, restore subtype: %{public}s.", cfgIme->subName.c_str()); - return SwitchSubtype(subProp); + return SwitchSubtypeWithoutStartIme(subProp); } bool PerUserSession::IsCurrentImeByPid(int32_t pid) @@ -1522,22 +1631,6 @@ int32_t PerUserSession::OnConnectSystemCmd(const sptr &channel, s return ErrorCode::NO_ERROR; } -bool PerUserSession::WaitForCurrentImeStop() -{ - IMSA_HILOGI("start."); - std::unique_lock lock(imeStopMutex_); - isSwitching_.store(true); - return imeStopCv_.wait_for(lock, std::chrono::milliseconds(STOP_IME_TIME), [this]() { return !isSwitching_; }); -} - -void PerUserSession::NotifyImeStopFinished() -{ - IMSA_HILOGI("start."); - std::unique_lock lock(imeStopMutex_); - isSwitching_.store(false); - imeStopCv_.notify_one(); -} - int32_t PerUserSession::RemoveAllCurrentClient() { std::lock_guard lock(clientGroupLock_); @@ -1599,13 +1692,18 @@ void PerUserSession::AddRestartIme() bool PerUserSession::RestartIme() { - auto task = [this]() { + // 1 - generate StartCurrentIme task + auto doStart = [this](ServiceResponseData &, ActionInnerData &) -> int32_t { if (CanStartIme()) { - auto ret = StartCurrentIme(true); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start ime failed!"); - } + return StartCurrentIme(true); } + return ErrorCode::NO_ERROR; + }; + auto onStartFail = [](int32_t) { IMSA_HILOGE("start ime failed!"); }; + auto doStartAction = std::make_unique(doStart, nullptr, onStartFail, false); + + // 2 - generate action after StartCurrentIme + auto afterStart = [this](ServiceResponseData &, ActionInnerData &) { int32_t tasks = 0; { std::lock_guard lock(restartMutex_); @@ -1615,17 +1713,11 @@ bool PerUserSession::RestartIme() std::lock_guard lock(restartMutex_); restartTasks_ = 0; } + return ErrorCode::NO_ERROR; }; - if (eventHandler_ == nullptr) { - IMSA_HILOGE("eventHandler_ is nullptr!"); - return false; - } - return eventHandler_->PostTask(task, "RestartCurrentImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); -} -BlockQueue& PerUserSession::GetSwitchQueue() -{ - return switchQueue_; + // pend the above two actions + return SaTaskManager::GetInstance().Pend(std::move(doStartAction), afterStart) == ErrorCode::NO_ERROR; } int32_t PerUserSession::InitImeData( @@ -1672,7 +1764,10 @@ int32_t PerUserSession::UpdateImeData(sptr core, sptrSetDeathRecipient([this, core, type](const wptr &) { this->OnImeDied(core, type); }); + std::string bundleName = it->second->ime.first; + deathRecipient->SetDeathRecipient([this, core, type, bundleName, pid](const wptr &) { + this->OnImeDied(core, type, bundleName, pid); + }); auto coreObject = core->AsObject(); if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) { IMSA_HILOGE("failed to add death recipient!"); @@ -1767,11 +1862,7 @@ int32_t PerUserSession::StartCurrentIme(const std::shared_ptr &ime } return StartInputService(ime); } - auto ret = ForceStopCurrentIme(); - if (ret != ErrorCode::NO_ERROR) { - return ret; - } - return StartInputService(ime); + return ForceClearAndStartIme(ime); } int32_t PerUserSession::HandleStartImeTimeout(const std::shared_ptr &ime) @@ -1787,20 +1878,39 @@ int32_t PerUserSession::HandleStartImeTimeout(const std::shared_ptr &ime) { - auto ret = StopCurrentIme(); - if (ret != ErrorCode::NO_ERROR) { - return ret; - } - return StartInputService(ime); + std::weak_ptr weakThis = shared_from_this(); + auto doStop = [weakThis](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->StopCurrentIme(); + }; + auto doStart = [weakThis, ime](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->StartInputService(ime); + }; + return SaTaskManager::GetInstance().Pend(doStop, doStart); +} + +int32_t PerUserSession::ForceClearAndStartIme(const std::shared_ptr &imeToStart, bool isWaitStop) +{ + std::weak_ptr weakThis = shared_from_this(); + auto doForceStop = [weakThis, isWaitStop](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->ForceStopCurrentIme(isWaitStop); + }; + auto doStart = [weakThis, imeToStart](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->StartInputService(imeToStart); + }; + return SaTaskManager::GetInstance().Pend(doForceStop, doStart); } int32_t PerUserSession::StopCurrentIme() @@ -1840,11 +1950,7 @@ int32_t PerUserSession::StopReadyCurrentIme() IMSA_HILOGE("StopInputService failed."); return ForceStopCurrentIme(); } - if (!WaitForCurrentImeStop()) { - IMSA_HILOGI("stop timeout."); - return ForceStopCurrentIme(); - } - return ErrorCode::NO_ERROR; + return WaitForImeStop(imeData->ime.first, imeData->ime.second); } int32_t PerUserSession::ForceStopCurrentIme(bool isNeedWait) @@ -1862,26 +1968,14 @@ int32_t PerUserSession::ForceStopCurrentIme(bool isNeedWait) if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) { StopClientInput(clientInfo); } - - AAFwk::Want want; - want.SetElementName(imeData->ime.first, imeData->ime.second); - auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility( - want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD); + auto ret = StopImeExtAbility(imeData->ime.first, imeData->ime.second); if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("StopExtensionAbility [%{public}s, %{public}s] failed, ret: %{public}d!", - imeData->ime.first.c_str(), imeData->ime.second.c_str(), ret); - return ErrorCode::ERROR_IMSA_IME_DISCONNECT_FAILED; + return ret; } if (!isNeedWait) { return ErrorCode::ERROR_IMSA_IME_START_MORE_THAN_EIGHT_SECOND; } - WaitForCurrentImeStop(); - if (ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) { - IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str()); - return ErrorCode::ERROR_IMSA_FORCE_STOP_IME_TIMEOUT; - } - RemoveImeData(ImeType::IME, true); - return ErrorCode::NO_ERROR; + return WaitForImeForceStop(imeData->ime.first, imeData->ime.second); } int32_t PerUserSession::HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme) @@ -1894,7 +1988,7 @@ int32_t PerUserSession::HandleFirstStart(const std::shared_ptr &im return ErrorCode::NO_ERROR; } if (BlockRetry(CHECK_IME_RUNNING_RETRY_INTERVAL, CHECK_IME_RUNNING_RETRY_TIMES, - [this]() -> bool { return !ImeInfoInquirer::GetInstance().IsRunningIme(userId_, runningIme_); })) { + [this]() -> bool { return !ImeInfoInquirer::GetInstance().IsRunningIme(userId_, runningIme_); })) { IMSA_HILOGI("[%{public}d, %{public}s] stop completely", userId_, runningIme_.c_str()); runningIme_.clear(); return StartInputService(ime); @@ -1917,13 +2011,12 @@ int32_t PerUserSession::RestoreCurrentIme(uint64_t callingDisplayId) && imeData->ime.second == cfgIme->extName) { return ErrorCode::NO_ERROR; } - IMSA_HILOGD("need restore!"); - auto ret = StartCurrentIme(); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start ime failed!"); - return ret; // ERROR_IME_START_FAILED - } - return ErrorCode::NO_ERROR; + // 1 - generate StartCurrentIme action + auto doStart = [this](ServiceResponseData &, ActionInnerData &) -> int32_t { return StartCurrentIme(); }; + auto onStartFail = [](int32_t ret) { IMSA_HILOGE("start ime failed, ret: %{public}d", ret); }; + auto startAction = std::make_unique(doStart, nullptr, onStartFail); + // 2 - pend StartCurrentIme action as next action + return SaTaskManager::GetInstance().Pend(std::move(startAction)); } bool PerUserSession::CheckPwdInputPatternConv(InputClientInfo &clientInfo, uint64_t displayId) @@ -1978,37 +2071,39 @@ bool PerUserSession::GetInputTypeToStart(std::shared_ptr &imeToSta return true; } -void PerUserSession::HandleImeBindTypeChanged( - InputClientInfo &newClientInfo, const std::shared_ptr &clientGroup) +void PerUserSession::HandleImeBindTypeChanged(InputClientInfo &newClientInfo) { - /* isClientInactive: true: represent the oldClientInfo is inactiveClient's - false: represent the oldClientInfo is currentClient's */ - std::shared_ptr oldClientInfo = nullptr; + /** + * isClientInactive true represent the oldClientInfo is of inactiveClient + * isClientInactive false represents the oldClientInfo is of currentClient + */ + auto clientGroup = GetClientGroup(newClientInfo.displayId); + if (clientGroup == nullptr) { + return; + } + auto oldClientInfo = clientGroup->GetCurrentClientInfo(); bool isClientInactive = false; - { - std::lock_guard lock(focusedClientLock_); - oldClientInfo = clientGroup->GetCurrentClientInfo(); - if (oldClientInfo == nullptr) { - auto inactiveClient = clientGroup->GetInactiveClient(); - if (inactiveClient != nullptr) { - oldClientInfo = clientGroup->GetClientInfo(inactiveClient->AsObject()); - isClientInactive = true; - } - } - if (oldClientInfo == nullptr) { - return; - } - if (!IsImeBindTypeChanged(oldClientInfo->bindImeType)) { - return; + if (oldClientInfo == nullptr) { + auto inactiveClient = clientGroup->GetInactiveClient(); + if (inactiveClient != nullptr) { + oldClientInfo = clientGroup->GetClientInfo(inactiveClient->AsObject()); + isClientInactive = true; } - // has current client, but new client is not current client - if (!isClientInactive && !IsSameClient(newClientInfo.client, oldClientInfo->client)) { - clientGroup->SetCurrentClient(nullptr); - if (oldClientInfo->client != nullptr) { - clientGroup->RemoveClientInfo(oldClientInfo->client->AsObject()); - } + } + if (oldClientInfo == nullptr) { + return; + } + if (!IsImeBindTypeChanged(oldClientInfo->bindImeType)) { + return; + } + // has current client, but new client is not current client + if (!isClientInactive && !IsSameClient(newClientInfo.client, oldClientInfo->client)) { + clientGroup->SetCurrentClient(nullptr); + if (oldClientInfo->client != nullptr) { + clientGroup->RemoveClientInfo(oldClientInfo->client->AsObject()); } } + IMSA_HILOGD("isClientInactive: %{public}d!", isClientInactive); if (IsSameClient(newClientInfo.client, oldClientInfo->client)) { newClientInfo.isNotifyInputStart = true; @@ -2137,7 +2232,7 @@ int32_t PerUserSession::NotifyCallingDisplayChanged(uint64_t displayId) IMSA_HILOGD("not default display"); return ErrorCode::NO_ERROR; } - auto data = GetValidIme(ImeType::IME); + auto data = GetReadyImeData(ImeType::IME); if (data == nullptr) { IMSA_HILOGE("ime is nullptr!"); return ErrorCode::ERROR_IME_NOT_STARTED; @@ -2187,6 +2282,11 @@ bool PerUserSession::GetCallingWindowInfo(const InputClientInfo &clientInfo, Cal return WindowAdapter::GetCallingWindowInfo(windowId, userId_, callingWindowInfo); } +bool PerUserSession::IsDefaultDisplayGroup(uint64_t displayId) +{ + return GetDisplayGroupId(displayId) == DEFAULT_DISPLAY_ID; +} + bool PerUserSession::SpecialScenarioCheck() { auto clientInfo = GetCurrentClientInfo(); @@ -2240,19 +2340,40 @@ int32_t PerUserSession::SpecialSendPrivateData(const std::unordered_map weakThis = shared_from_this(); + auto doStart = [weakThis, imeExtendInfo](ServiceResponseData &, ActionInnerData &innerData) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + ImeLaunchType type; + int32_t ret = sharedThis->StartPreconfiguredDefaultIme(DEFAULT_DISPLAY_ID, type, imeExtendInfo, true); + innerData = type; return ret; - } - if (status == StartPreDefaultImeStatus::NO_NEED || status == StartPreDefaultImeStatus::TO_START) { + }; + auto onFailure = [](int32_t ret) { IMSA_HILOGE("start pre default ime failed, ret: %{public}d!", ret); }; + auto doStartAction = std::make_unique(doStart, nullptr, onFailure); + + // 2 - generate SendPrivateData action + auto doSendPrivateData = [weakThis, privateCommand](ServiceResponseData &, ActionInnerData &innerData) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + ImeLaunchType type; + if (!VariantUtil::GetValue(innerData, type)) { + return ErrorCode::ERROR_INVALID_VARIANT_TYPE; + } + if (type != ImeLaunchType::ALREADY_LAUNCHED) { + return ErrorCode::NO_ERROR; + } + int32_t ret = sharedThis->SendPrivateData(privateCommand); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Notify send private data failed, ret: %{public}d!", ret); + } return ret; - } - ret = SendPrivateData(privateCommand); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("Notify send private data failed, ret: %{public}d!", ret); - } - return ret; + }; + + // pend above two actions + return SaTaskManager::GetInstance().Pend(std::move(doStartAction), doSendPrivateData); } int32_t PerUserSession::SendPrivateData(const std::unordered_map &privateCommand) @@ -2278,11 +2399,6 @@ int32_t PerUserSession::SendPrivateData(const std::unordered_map &clientInfo) { clientInfo->requestKeyboardReason = RequestKeyboardReason::NONE; @@ -2315,25 +2431,100 @@ bool PerUserSession::AllowSwitchImeByCombinationKey() return !IsPreconfiguredDefaultImeSpecified(*clientInfo); } -std::pair PerUserSession::StartPreconfiguredDefaultIme( - uint64_t callingDisplayId, const ImeExtendInfo &imeExtendInfo, bool isStopCurrentIme) +int32_t PerUserSession::StartPreconfiguredDefaultIme( + uint64_t callingDisplayId, ImeLaunchType &launchType, const ImeExtendInfo &imeExtendInfo, bool isStopCurrentIme) { if (!IsDefaultDisplayGroup(callingDisplayId)) { IMSA_HILOGI("only start in default display, calling display: %{public}" PRIu64 "", callingDisplayId); - return std::make_pair(ErrorCode::NO_ERROR, StartPreDefaultImeStatus::NO_NEED); + launchType = ImeLaunchType::LAUNCH_SKIPPED; + return ErrorCode::NO_ERROR; } InputTypeManager::GetInstance().Set(false); auto preDefaultIme = ImeInfoInquirer::GetInstance().GetDefaultIme(); auto ime = GetReadyImeData(ImeType::IME); if (ime != nullptr && (ime->ime.first == preDefaultIme.bundleName && ime->ime.second == preDefaultIme.extName)) { - return std::make_pair(ErrorCode::NO_ERROR, StartPreDefaultImeStatus::HAS_STARTED); + launchType = ImeLaunchType::ALREADY_LAUNCHED; + return ErrorCode::NO_ERROR; } + launchType = ImeLaunchType::NEEDS_LAUNCH; preDefaultIme.imeExtendInfo = imeExtendInfo; - auto ret = StartIme(std::make_shared(preDefaultIme), isStopCurrentIme); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start ime failed, ret: %{public}d!", ret); + + // generate StartIme action + std::weak_ptr weakThis = shared_from_this(); + auto doStart = [weakThis, preDefaultIme, isStopCurrentIme](ServiceResponseData &, ActionInnerData &) -> int32_t { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->StartIme(std::make_shared(preDefaultIme), isStopCurrentIme); + }; + auto onFail = [](int32_t ret) { IMSA_HILOGE("start ime failed, ret: %{public}d!", ret); }; + auto doStartAction = std::make_unique(doStart, nullptr, onFail); + // pend StartIme to next action + return SaTaskManager::GetInstance().Pend(std::move(doStartAction)); +} + +int32_t PerUserSession::WaitForImeStart(const std::shared_ptr &ime) +{ + if (ime == nullptr) { + IMSA_HILOGE(""); + return ErrorCode::ERROR_NULL_POINTER; } - return std::make_pair(ret, StartPreDefaultImeStatus::TO_START); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = ime->bundleName }; + SaActionFunc onComplete = [ime](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGI("%{public}s started successfully.", ime->imeId.c_str()); + InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME); + return ErrorCode::NO_ERROR; + }; + SaActionFunc onTimeout = [ime](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGE("start %{public}s timeout!", ime->imeId.c_str()); + return ErrorCode::ERROR_IMSA_IME_START_TIMEOUT; + }; + auto waitAction = std::make_unique(MAX_IME_START_TIME, info, onComplete, onTimeout); + return SaTaskManager::GetInstance().WaitExec(std::move(waitAction)); +} + +void PerUserSession::NotifyImeStartReady(const CallerInfo &info) +{ + IMSA_HILOGI("%{public}s", info.bundleName.c_str()); + SaTaskManager::GetInstance().TryResume(PauseType::PAUSE_TYPE_START_IME, info); +} + +int32_t PerUserSession::WaitForImeStop(const std::string &bundleName, const std::string &extName) +{ + std::weak_ptr weakThis = shared_from_this(); + auto onTimeout = [weakThis, bundleName, extName](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", bundleName.c_str(), extName.c_str()); + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + return sharedThis->ForceStopCurrentIme(); + }; + PauseInfo info = { .type = PauseType::PAUSE_TYPE_STOP_IME, .target = bundleName }; + auto waitAction = std::make_unique(STOP_IME_TIME, info, nullptr, onTimeout); + return SaTaskManager::GetInstance().WaitExec(std::move(waitAction)); +} + +int32_t PerUserSession::WaitForImeForceStop(const std::string &bundleName, const std::string &extName) +{ + std::weak_ptr weakThis = shared_from_this(); + auto checkStopResult = [weakThis, bundleName, extName](ServiceResponseData &, ActionInnerData &) { + std::shared_ptr sharedThis = nullptr; + GET_SHARED_THIS(weakThis, sharedThis, ErrorCode::ERROR_IMSA_NULLPTR); + if (ImeInfoInquirer::GetInstance().IsRunningIme(sharedThis->userId_, bundleName)) { + IMSA_HILOGW("force stop [%{public}s, %{public}s] timeout.", bundleName.c_str(), extName.c_str()); + return ErrorCode::ERROR_IMSA_FORCE_STOP_IME_TIMEOUT; + } + sharedThis->RemoveImeData(ImeType::IME, true); + return ErrorCode::NO_ERROR; + }; + PauseInfo info = { .type = PauseType::PAUSE_TYPE_STOP_IME, .target = bundleName }; + auto waitStop = std::make_unique(STOP_IME_TIME, info); + return SaTaskManager::GetInstance().WaitExec(std::move(waitStop), checkStopResult); +} + +void PerUserSession::NotifyImeStopFinished(const std::string &bundleName) +{ + IMSA_HILOGI("%{public}s", bundleName.c_str()); + CallerInfo info = { .bundleName = bundleName }; + SaTaskManager::GetInstance().TryResume(PauseType::PAUSE_TYPE_STOP_IME, info); } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/user_session_manager.cpp b/services/src/user_session_manager.cpp index 23001ff1ad320273ad4d143456205adb5caa342f..b3b135b46fba76494f1e3b94319a472086462863 100644 --- a/services/src/user_session_manager.cpp +++ b/services/src/user_session_manager.cpp @@ -47,7 +47,7 @@ void UserSessionManager::AddUserSession(int32_t userId) if (session != userSessions_.end()) { return; } - auto sessionTemp = std::make_shared(userId, eventHandler_); + auto sessionTemp = std::make_shared(userId); userSessions_.insert({ userId, sessionTemp }); } @@ -56,10 +56,5 @@ void UserSessionManager::RemoveUserSession(int32_t userId) std::lock_guard lock(userSessionsLock_); userSessions_.erase(userId); } - -void UserSessionManager::SetEventHandler(const std::shared_ptr &eventHandler) -{ - eventHandler_ = eventHandler; -} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/task_manager/include/actions/sa_action.h b/services/task_manager/include/actions/sa_action.h new file mode 100644 index 0000000000000000000000000000000000000000..86274b0f8eb4bdc38d1f0734355a6bdffb190c05 --- /dev/null +++ b/services/task_manager/include/actions/sa_action.h @@ -0,0 +1,107 @@ +/* + * 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 IMF_SERVICES_SA_ACTION_NEW_H +#define IMF_SERVICES_SA_ACTION_NEW_H + +#include +#include + +#include "action.h" +#include "input_client_info.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +static constexpr int32_t INVALID_RET_CODE = -1; +enum class PauseType : int32_t { + PAUSED_TYPE_INVALID = -1, + PAUSE_TYPE_START_IME = 0, + PAUSE_TYPE_STOP_IME, +}; + +struct PauseInfo { + PauseType type{ PauseType::PAUSED_TYPE_INVALID }; // pause type + std::string target; // bundleName of waiting target + uint64_t resumeId{ 0 }; + inline std::string ToString() const + { + std::stringstream ss; + ss << "PausedInfo:[" + << "type: " << static_cast(type) << " target: " << target.c_str() << " resumeId: " << resumeId + << "]"; + return ss.str(); + } +}; + +using ActionInnerData = std::variant; +using ResultHandler = std::function; +using SaActionFunc = std::function; +class SaAction { +public: + SaAction() = default; + explicit SaAction(SaActionFunc func) : func_(std::move(func)), isResultAffectParent_(true) + { + } + SaAction(SaActionFunc func, ResultHandler onSuccess, ResultHandler onFailure) + : func_(std::move(func)), onSuccess_(std::move(onSuccess)), onFailure_(std::move(onFailure)), + isResultAffectParent_(true), failureCode_(INVALID_RET_CODE) + { + } + SaAction(SaActionFunc func, ResultHandler onSuccess, ResultHandler onFailure, bool isAffect, + int32_t failureCode = INVALID_RET_CODE) + : func_(std::move(func)), onSuccess_(std::move(onSuccess)), onFailure_(std::move(onFailure)), + isResultAffectParent_(isAffect), failureCode_(failureCode) + { + } + virtual ~SaAction() = default; + + virtual RunningState Execute(int32_t &ret, ServiceResponseData &responseData); + virtual RunningState Resume(uint64_t resumedId, int32_t &ret, ServiceResponseData &data); + virtual int32_t Pend(std::unique_ptr action); + virtual PauseInfo GetPausedInfo(); + + virtual RunningState Execute(int32_t &ret, ServiceResponseData &responseData, ActionInnerData &innerData); + virtual RunningState Resume( + uint64_t resumedId, int32_t &ret, ServiceResponseData &data, ActionInnerData &innerData); + + RunningState GetState() const; + +protected: + RunningState state_{ RUNNING_STATE_IDLE }; + +private: + RunningState ExecuteInner(int32_t &ret, ServiceResponseData &responseData); + + RunningState ExecuteImpl(ServiceResponseData &responseData); + + bool hasFuncExecuted_{ false }; + SaActionFunc func_; + ResultHandler onSuccess_{ nullptr }; + ResultHandler onFailure_{ nullptr }; + + bool isResultAffectParent_{ true }; + + std::unique_ptr curSubAction_{ nullptr }; + std::list> subActions_; + + int32_t retCode_{ 0 }; + int32_t failureCode_{ INVALID_RET_CODE }; + ActionInnerData innerData_{ std::monostate{} }; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_SERVICES_SA_ACTION_NEW_H diff --git a/common/src/message_handler.cpp b/services/task_manager/include/actions/sa_action_report.h similarity index 31% rename from common/src/message_handler.cpp rename to services/task_manager/include/actions/sa_action_report.h index 11f3eac663ff9b0f112c6a73a9acabab0ac1305a..0a0e87ecaf56a9a5bbe6036b50b3549d5a9f5f2b 100644 --- a/common/src/message_handler.cpp +++ b/services/task_manager/include/actions/sa_action_report.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -13,65 +13,40 @@ * limitations under the License. */ -#include "inputmethod_message_handler.h" +#ifndef IMF_SERVICES_SA_ACTION_REPORT_H +#define IMF_SERVICES_SA_ACTION_REPORT_H + +#include "sa_action.h" namespace OHOS { namespace MiscServices { -std::mutex MessageHandler::handlerMutex_; - -MessageHandler::MessageHandler() -{ -} - -MessageHandler::~MessageHandler() -{ - std::unique_lock lock(mMutex); - while (!mQueue.empty()) { - Message *msg = mQueue.front(); - mQueue.pop(); - delete msg; - msg = nullptr; +using ReportFunc = std::function; +class SaActionReport : public SaAction { +public: + SaActionReport() = default; + explicit SaActionReport(ReportFunc func) : func_(std::move(func)) + { } -} - -/*! Send a message - * @param msg a message to be sent - * @note the msg pointer should not be freed by the caller - */ -void MessageHandler::SendMessage(Message *msg) -{ - std::unique_lock lock(mMutex); - mQueue.push(msg); - mCV.notify_one(); -} + ~SaActionReport() = default; -/*! Get a message - * @return a pointer referred to an object of message - * @note the returned pointer should be freed by the caller. - */ -Message *MessageHandler::GetMessage() -{ - std::unique_lock lock(mMutex); - mCV.wait(lock, [this] { return !this->mQueue.empty(); }); - Message *msg = reinterpret_cast(mQueue.front()); - mQueue.pop(); - return msg; -} + RunningState Execute(int32_t &ret, ServiceResponseData &responseData) override + { + if (state_ != RUNNING_STATE_IDLE) { + return RUNNING_STATE_ERROR; + } -/*! The single instance of MessageHandler in the service - * @return the pointer referred to an object. - */ -MessageHandler *MessageHandler::Instance() -{ - static MessageHandler *handler = nullptr; - if (handler == nullptr) { - std::unique_lock lock(handlerMutex_); - if (handler == nullptr) { - handler = new (std::nothrow) MessageHandler(); - return handler; + state_ = RUNNING_STATE_RUNNING; + if (func_) { + func_(ret, responseData); } + state_ = RUNNING_STATE_COMPLETED; + return state_; } - return handler; -} + +private: + ReportFunc func_; +}; } // namespace MiscServices } // namespace OHOS + +#endif // IMF_SERVICES_SA_ACTION_REPORT_H diff --git a/services/task_manager/include/actions/sa_action_wait.h b/services/task_manager/include/actions/sa_action_wait.h new file mode 100644 index 0000000000000000000000000000000000000000..57710e853a12f6122700b1ebc0239398b60478c6 --- /dev/null +++ b/services/task_manager/include/actions/sa_action_wait.h @@ -0,0 +1,62 @@ +/* + * 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 IMF_SERVICES_SA_ACTION_WAIT_H +#define IMF_SERVICES_SA_ACTION_WAIT_H + +#include + +#include "sa_action.h" +#include "sa_task.h" + +namespace OHOS { +namespace MiscServices { +class SaActionWait : public SaAction { +public: + SaActionWait(uint32_t timeoutMs, PauseInfo info) + : completeId_(SaTask::GetNextSeqId()), timeoutId_(SaTask::GetNextSeqId()), timeoutMs_(timeoutMs), + pauseInfo_(std::move(info)), onComplete_(nullptr), onTimeout_(nullptr) + { + pauseInfo_.resumeId = completeId_; + } + SaActionWait(uint32_t timeoutMs, PauseInfo info, SaActionFunc onComplete, SaActionFunc onTimeout) + : completeId_(SaTask::GetNextSeqId()), timeoutId_(SaTask::GetNextSeqId()), timeoutMs_(timeoutMs), + pauseInfo_(std::move(info)), onComplete_(std::move(onComplete)), onTimeout_(std::move(onTimeout)) + { + pauseInfo_.resumeId = completeId_; + } + + ~SaActionWait() = default; + + RunningState Execute(int32_t &ret, ServiceResponseData &responseData) override; + RunningState Execute(int32_t &ret, ServiceResponseData &responseData, ActionInnerData &innerData) override; + + RunningState Resume(uint64_t resumedId, int32_t &ret, ServiceResponseData &data) override; + RunningState Resume( + uint64_t resumedId, int32_t &ret, ServiceResponseData &data, ActionInnerData &innerData) override; + + PauseInfo GetPausedInfo() override; + +private: + const uint64_t completeId_; + const uint64_t timeoutId_; + const uint32_t timeoutMs_; + PauseInfo pauseInfo_{}; + SaActionFunc onComplete_; + SaActionFunc onTimeout_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // IMF_SERVICES_SA_ACTION_WAIT_H diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability_utils.h b/services/task_manager/include/caller_info.h similarity index 61% rename from frameworks/native/inputmethod_ability/include/input_method_ability_utils.h rename to services/task_manager/include/caller_info.h index e3578e4bc59e713e02427af8b6050861ed0c254b..bb45f345c252ef4c22474331c4b8c9293bfe2c37 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability_utils.h +++ b/services/task_manager/include/caller_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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 @@ -13,22 +13,25 @@ * limitations under the License. */ -#ifndef INPUT_METHOD_ABILITY_UTILS_H -#define INPUT_METHOD_ABILITY_UTILS_H +#ifndef IMF_CALLER_INFO_H +#define IMF_CALLER_INFO_H -#include "input_method_system_ability_proxy.h" +#include + +#include namespace OHOS { namespace MiscServices { -class ImaUtils { -public: - static sptr GetImsaProxy(); - -private: - static std::mutex abilityLock_; - static sptr abilityManager_; // for tdd test +static constexpr int32_t MAIN_USER_ID = 100; +struct CallerInfo { + uint32_t requestId = 0; + int32_t pid = 0; + int32_t uid = 0; + int32_t userId{ MAIN_USER_ID }; + uint32_t tokenId = 0; + uint64_t fullTokenId = 0; + std::string bundleName; }; } // namespace MiscServices } // namespace OHOS - -#endif // INPUT_METHOD_ABILITY_UTILS_H +#endif // IMF_CALLER_INFO_H diff --git a/services/task_manager/include/requester_manager.h b/services/task_manager/include/requester_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..2df4d91c51825b1e69bba21a7d7c5034779c61f3 --- /dev/null +++ b/services/task_manager/include/requester_manager.h @@ -0,0 +1,68 @@ +/* + * 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 IMF_SERVICES_REQUESTER_MANAGER_H +#define IMF_SERVICES_REQUESTER_MANAGER_H + +#include + +#include +#include +#include + +#include "input_death_recipient.h" +#include "iremote_object.h" +#include "iima_response_channel.h" +#include "iimc_response_channel.h" + +namespace OHOS { +namespace MiscServices { +struct RequesterInfo { + uint32_t requestCount{ 0 }; + sptr imaResponseChannel{ nullptr }; + sptr imcResponseChannel{ nullptr }; + sptr deathRecipient{ nullptr }; +}; + +class RequesterManager : public std::enable_shared_from_this { +private: + RequesterManager() = default; + +public: + ~RequesterManager() = default; + + RequesterManager(const RequesterManager &) = delete; + RequesterManager(RequesterManager &&) = delete; + RequesterManager &operator=(const RequesterManager &) = delete; + RequesterManager &operator=(RequesterManager &&) = delete; + + static RequesterManager &GetInstance(); + + std::shared_ptr GetRequester(int32_t pid); + int32_t AddImaChannel(int32_t pid, sptr channel); + int32_t AddImcChannel(int32_t pid, sptr channel); + + void TaskIn(int32_t pid); + void TaskOut(int32_t pid); + +private: + void OnClientDied(int32_t pid); + std::mutex mutex_{}; + std::unordered_map> requesterMap_; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_SERVICES_REQUESTER_MANAGER_H diff --git a/services/task_manager/include/sa_task_manager.h b/services/task_manager/include/sa_task_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..d75d2a5f7b7ac3cbf7232d60134247770218ee22 --- /dev/null +++ b/services/task_manager/include/sa_task_manager.h @@ -0,0 +1,128 @@ +/* + * 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 IMF_SERVICES_SA_TASK_MANAGER_H +#define IMF_SERVICES_SA_TASK_MANAGER_H + +#include "event_handler.h" +#include "input_method_utils.h" +#include "sa_action.h" +#include "sa_action_wait.h" +#include "sa_task.h" + +namespace OHOS { +namespace MiscServices { +using CallBack = std::function; + +using SaTaskPtr = std::shared_ptr; +using SaActionPtr = std::unique_ptr; + +#define GET_SHARED_THIS(weakThis, sharedThis, retVal) \ + do { \ + sharedThis = weakThis.lock(); \ + if (sharedThis == nullptr) { \ + IMSA_HILOGE("sharedThis is nullptr"); \ + return retVal; \ + } \ + } while (0) + +#define GET_SHARED_THIS_RETURN_VOID(weakThis, sharedThis) \ + do { \ + sharedThis = weakThis.lock(); \ + if (sharedThis == nullptr) { \ + IMSA_HILOGE("sharedThis is nullptr"); \ + return; \ + } \ + } while (0) + +class SaTaskManager final { +private: + SaTaskManager(); + +public: + ~SaTaskManager() = default; + + SaTaskManager(const SaTaskManager &) = delete; + SaTaskManager(SaTaskManager &&) = delete; + SaTaskManager &operator=(const SaTaskManager &) = delete; + SaTaskManager &operator=(SaTaskManager &&) = delete; + + static SaTaskManager &GetInstance(); + + // Post a task to work thread + int32_t PostTask(SaTaskPtr task, uint32_t delayMs = 0); + + // Trigger task process async + void ProcessAsync(); + + // Resume paused task with seqId + void Complete(uint64_t resumeId); + + // Pend an action to current task during executing + int32_t Pend(SaActionPtr action); + int32_t Pend(const SaActionFunc &func); + template int32_t Pend(Args &&... args) + { + if (curTask_ == nullptr || !curTask_->IsRunning()) { + IMSA_HILOGE("curTask_ is NULL or not running, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + return curTask_->Pend(std::forward(args)...); + } + + // Wait for task and execute + int32_t WaitExec(std::unique_ptr waitAction, SaActionFunc execFunc = nullptr); + // Try to resume the current paused task + void TryResume(const PauseType &pauseType, const CallerInfo &callerInfo); + +private: + friend class InputMethodSystemAbility; + friend class SaActionWait; + void SetInited(bool flag); + void Reset(); + int32_t PendWaitResult(const SaActionFunc &func); + +private: + void OnNewTask(SaTaskPtr task); // Accept a new task + void Process(); // Process next task + + void ProcessNextCriticalTask(); + void ProcessNextSwitchImeTask(); + void ProcessNextHigherRequestTask(); + void ProcessNextNormalRequestTask(); + void ProcessNextQueryTask(); + void ProcessNextResumeTask(); + void ProcessNextInnerTask(); + + void ExecuteCurrentTask(); // Execute current task + +private: + bool IsWhiteListRequest(SaTaskCode taskCode); + bool inited_{ false }; + std::shared_ptr eventHandler_{ nullptr }; + + SaTaskPtr curTask_ = { nullptr }; + SaTaskPtr pausedTask_ = { nullptr }; + std::list criticalTasks_; + std::list switchImeTasks_; + std::list higherRequestTasks_; + std::list normalRequestTasks_; + std::list queryTasks_; + std::list innerTasks_; + std::list resumeTasks_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // IMF_SERVICES_SA_TASK_MANAGER_H \ No newline at end of file diff --git a/services/task_manager/include/tasks/sa_task.h b/services/task_manager/include/tasks/sa_task.h new file mode 100644 index 0000000000000000000000000000000000000000..455b8c307b30ade66e975356ad9b353343f1e171 --- /dev/null +++ b/services/task_manager/include/tasks/sa_task.h @@ -0,0 +1,255 @@ +/* + * 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 IMF_SERVICES_SA_TASK_H +#define IMF_SERVICES_SA_TASK_H + +#include "caller_info.h" +#include "iima_response_channel.h" +#include "iimc_response_channel.h" +#include "sa_action.h" +#include "sa_action_report.h" +#include "service_response_data.h" + +namespace OHOS { +namespace MiscServices { +constexpr uint32_t INVALID_SEQ_ID = 0; +enum class SaTaskType : int32_t { + TYPE_CRITICAL_CHANGE = 0, // tasks bringing critical changes or updates + TYPE_SWITCH_IME = 1, // tasks causing ime switch + TYPE_HIGHER_REQUEST = 2, // tasks with a higher priority request + TYPE_NORMAL_REQUEST = 3, // tasks with a normal priority request + TYPE_RESUME = 4, // tasks creating resume inner tasks + TYPE_QUERY = 5, // tasks used for querying + TYPE_INNER = 6, // tasks acting on the current paused task + + TYPE_TOTAL_COUNT, + TYPE_INVALID = -1, +}; + +#define TASK_TYPE_OFFSET(src) ((src)*10000) + +enum class SaTaskCode : uint32_t { + TASK_CRITICAL_CHANGE_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_CRITICAL_CHANGE)), + // user change + ON_USER_STARTED, + ON_USER_REMOVED, + ON_USER_STOPPED, + // scb status change + ON_WMS_CONNECTED, + ON_WMS_DISCONNECTED, + // changes update ime info + ON_BUNDLE_SCAN_FINISHED, + ON_DATA_SHARE_READY, + // change current ime state + ON_EXTENSION, + ON_IME_ENABLED_STATE_CHANGED, + ON_IME_LIFE_CYCLE_STOP, + // on critical sa started + ON_ACCOUNT_SA_STARTED, + ON_MEM_SA_STARTED, + ON_WMS_SA_STARTED, + TASK_CRITICAL_CHANGE_END, + + TASK_SWITCH_IME_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_SWITCH_IME)), + // proxy ime register from IPC + REGISTER_PROXY_IME, + UNREGISTER_PROXY_IME, + UNREGISTERED_PROXY_IME, + // switch ime requests from IPC + SWITCH_INPUT_METHOD, + START_INPUT_TYPE, + EXIT_CURRENT_INPUT_TYPE, + // events which may switch ime + ON_PACKAGE_REMOVED, + ON_SCREEN_UNLOCKED, + TASK_SWITCH_IME_END, + + TASK_HIGHER_REQUEST_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_HIGHER_REQUEST)), + // events which influence user typing or panel showing + ON_FOCUSED, + ON_UNFOCUSED, + ON_COMMON_EVENT_SA_STARTED, + ON_DISPLAY_ID_CHANGED, + ON_MMI_SA_STARTED, + TASK_HIGHER_REQUEST_END, + + TASK_NORMAL_REQUEST_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_NORMAL_REQUEST)), + // operate keyboard from IPC + START_INPUT, + SHOW_CURRENT_INPUT, + HIDE_CURRENT_INPUT, + STOP_INPUT_SESSION, + SHOW_INPUT, + HIDE_INPUT, + RELEASE_INPUT, + REQUEST_SHOW_INPUT, + REQUEST_HIDE_INPUT, + CONNECT_SYSTEM_CMD, + SHOW_CURRENT_INPUT_DEPRECATED, + HIDE_CURRENT_INPUT_DEPRECATED, + HIDE_KEYBOARD_SELF, + ON_PASTEBOARD_SA_STARTED, + // data transaction or info setting requests from IPC + SET_CALLING_WINDOW, + SEND_PRIVATE_DATA, + PANEL_STATUS_CHANGE, + UPDATE_LISTEN_EVENT_FLAG, + DISPLAY_OPTIONAL_INPUT_METHOD, + TASK_NORMAL_REQUEST_END, + + TASK_RESUME_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_RESUME)), + // resume pause for ime start + INIT_CONNECT, + SET_CORE_AND_AGENT, + // resume pause for ime stop + ON_IME_DIED, + TASK_RESUME_END, + + TASK_QUERY_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_QUERY)), + // Get imf info + GET_CURRENT_INPUT_METHOD, + GET_CURRENT_INPUT_METHOD_SUBTYPE, + GET_DEFAULT_INPUT_METHOD, + GET_INPUT_METHOD_CONFIG, + GET_INPUT_METHOD_STATE, + GET_INPUT_START_INFO, + GET_SECURITY_MODE, + // List ime info + LIST_INPUT_METHOD, + LIST_INPUT_METHOD_SUBTYPE, + LIST_CURRENT_INPUT_METHOD_SUBTYPE, + // Judge ime info + IS_CURRENT_IME, + IS_CURRENT_IME_BY_PID, + IS_DEFAULT_IME, + IS_DEFAULT_IME_SCREEN, + IS_DEFAULT_IME_SET, + IS_INPUT_TYPE_SUPPORTED, + IS_PANEL_SHOWN, + IS_SYSTEM_APP, + IS_SYSTEM_IME_APP, + // Operate or update ime info + ENABLE_IME, + ON_BOOT_COMPLETED, + ON_DATA_SHARE_CALLBACK, + ON_PACKAGE_ADDED, + ON_PACKAGE_CHANGED, + ON_UPDATE_GLOBAL_ENABLED_TABLE, + ON_UPDATE_IME_INFO, + ON_SYSTEM_LANGUAGE_CHANGED, + TASK_QUERY_END, + + TASK_INNER_BEGIN = TASK_TYPE_OFFSET(static_cast(SaTaskType::TYPE_INNER)), + RESUME_WAIT, + RESUME_TIMEOUT, + TASK_INNER_END, +}; + +class SaTask { +public: + explicit SaTask(SaTaskCode code) + : code_(code), seqId_(GetNextSeqId()), imaResponseChannel_(nullptr), imcResponseChannel_(nullptr) + { + } + SaTask(SaTaskCode code, uint64_t seqId) + : code_(code), seqId_(seqId), imaResponseChannel_(nullptr), imcResponseChannel_(nullptr) + { + } + SaTask(SaTaskCode code, SaActionFunc func) + : code_(code), seqId_(GetNextSeqId()), imaResponseChannel_(nullptr), imcResponseChannel_(nullptr) + { + action_ = std::make_unique(func); + } + SaTask(SaTaskCode code, std::unique_ptr action) + : code_(code), seqId_(GetNextSeqId()), imaResponseChannel_(nullptr), imcResponseChannel_(nullptr) + { + action_ = std::move(action); + } + SaTask(SaTaskCode code, SaActionFunc func, CallerInfo info) + : code_(code), seqId_(GetNextSeqId()), callerInfo_(info), imaResponseChannel_(nullptr), + imcResponseChannel_(nullptr) + { + action_ = std::make_unique(func); + } + SaTask(SaTaskCode code, SaActionFunc func, CallerInfo info, sptr channel) + : code_(code), seqId_(GetNextSeqId()), callerInfo_(info), imaResponseChannel_(channel), + imcResponseChannel_(nullptr) + { + action_ = std::make_unique(func); + } + SaTask(SaTaskCode code, SaActionFunc func, CallerInfo info, sptr channel) + : code_(code), seqId_(GetNextSeqId()), callerInfo_(info), imaResponseChannel_(nullptr), + imcResponseChannel_(channel) + { + action_ = std::make_unique(func); + } + ~SaTask(); + + static uint64_t GetNextSeqId(); + + void SetHiSysReporter(const ReportFunc &func); + + RunningState Execute(); + RunningState Resume(uint64_t resumeId); + RunningState OnTask(const std::shared_ptr &task); + + // Pend an action to the task directly. + int32_t PendSingle(std::unique_ptr action); + // Pend an action to the task, of which properties will inherit curAction_. + int32_t PendSingle(SaActionFunc func); + template int32_t Pend(Args &&... args) + { + return (PendSingle(std::forward(args)) && ...); + } + + // get task info + SaTaskType GetType() const; + SaTaskCode GetCode() const; + uint64_t GetSeqId() const; + CallerInfo GetCallerInfo() const; + bool IsRunning() const; + bool IsPaused() const; + PauseInfo GetPauseInfo(); + + void OnResponse(int32_t retCode); + +private: + RunningState ExecuteInner(); + void InvokeResponse(); + +protected: + static constexpr int32_t INVALID_FAIL_CODE = -1; + RunningState state_{ RUNNING_STATE_IDLE }; + + const SaTaskCode code_; + const uint64_t seqId_; + + CallerInfo callerInfo_; + sptr imaResponseChannel_; + sptr imcResponseChannel_; + ServiceResponseData responseData_{ std::monostate{} }; + + bool hasResponded_{ false }; + int32_t failRet_{ INVALID_FAIL_CODE }; + int32_t retCode_{ ErrorCode::NO_ERROR }; + + std::unique_ptr action_{ nullptr }; + std::unique_ptr hiSysReporter_{ nullptr }; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // IMF_SERVICES_SA_TASK_H diff --git a/services/task_manager/src/actions/sa_action.cpp b/services/task_manager/src/actions/sa_action.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef213b6fd776f6a581e028e538eb3f9d76d5e7b3 --- /dev/null +++ b/services/task_manager/src/actions/sa_action.cpp @@ -0,0 +1,199 @@ +/* + * 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 "sa_action.h" + +#include "variant_util.h" + +namespace OHOS { +namespace MiscServices { +RunningState SaAction::Execute(int32_t &ret, ServiceResponseData &responseData) +{ + if (state_ != RUNNING_STATE_IDLE) { + return RUNNING_STATE_ERROR; + } + return ExecuteInner(ret, responseData); +} + +RunningState SaAction::Execute(int32_t &ret, ServiceResponseData &responseData, ActionInnerData &innerData) +{ + if (state_ != RUNNING_STATE_IDLE) { + return RUNNING_STATE_ERROR; + } + innerData_ = innerData; + auto state = ExecuteInner(ret, responseData); + innerData = innerData_; + return state; +} + +RunningState SaAction::Resume(uint64_t resumedId, int32_t &ret, ServiceResponseData &data) +{ + if (curSubAction_ == nullptr) { + IMSA_HILOGE("curSubAction_ is nullptr"); + return RUNNING_STATE_ERROR; + } + + if (state_ != RUNNING_STATE_PAUSED) { + IMSA_HILOGE("state_ is %{public}u, do not need to resume", state_); + return RUNNING_STATE_ERROR; + } + + auto state = curSubAction_->Resume(resumedId, ret, data); + if (state == RUNNING_STATE_PAUSED) { + return state_; + } + if (state == RUNNING_STATE_COMPLETED) { + curSubAction_.reset(); + return ExecuteInner(ret, data); + } + IMSA_HILOGE("curAction_ resume return %{public}u, error!", state); + return RUNNING_STATE_ERROR; +} + +RunningState SaAction::Resume(uint64_t resumedId, int32_t &ret, ServiceResponseData &data, ActionInnerData &innerData) +{ + if (curSubAction_ == nullptr) { + IMSA_HILOGE("curSubAction_ is nullptr"); + return RUNNING_STATE_ERROR; + } + + if (state_ != RUNNING_STATE_PAUSED) { + IMSA_HILOGE("state_ is %{public}u, do not need to resume", state_); + return RUNNING_STATE_ERROR; + } + + auto state = curSubAction_->Resume(resumedId, ret, data, innerData); + if (state == RUNNING_STATE_PAUSED) { + return state_; + } + if (state == RUNNING_STATE_COMPLETED) { + curSubAction_.reset(); + return ExecuteInner(ret, data); + } + IMSA_HILOGE("curAction_ resume return %{public}u, error!", state); + return RUNNING_STATE_ERROR; +} + +int32_t SaAction::Pend(std::unique_ptr action) +{ + if (action == nullptr) { + IMSA_HILOGE("action is nullptr"); + return ErrorCode::ERROR_NULL_POINTER; + } + + if (state_ != RUNNING_STATE_RUNNING) { + IMSA_HILOGE("curTask_ is not running, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + + if (curSubAction_ == nullptr) { + subActions_.push_back(std::move(action)); + return ErrorCode::NO_ERROR; + } + + return curSubAction_->Pend(std::move(action)); +} + +PauseInfo SaAction::GetPausedInfo() +{ + if (state_ != RUNNING_STATE_PAUSED) { + return {}; + } + if (curSubAction_ == nullptr) { + return {}; + } + return curSubAction_->GetPausedInfo(); +} + +RunningState SaAction::GetState() const +{ + return state_; +} + +RunningState SaAction::ExecuteInner(int32_t &ret, ServiceResponseData &responseData) +{ + state_ = RUNNING_STATE_RUNNING; + + state_ = ExecuteImpl(responseData); + + // state is paused, return. + if (state_ == RUNNING_STATE_PAUSED) { + return state_; + } + + // state error + if (state_ == RUNNING_STATE_ERROR) { + return state_; + } + + // state is RUNNING_STATE_COMPLETED + ResultHandler handler = nullptr; + if (retCode_ != ErrorCode::NO_ERROR) { + // return failureCode_ if valid + retCode_ = failureCode_ != INVALID_RET_CODE ? failureCode_ : retCode_; + handler = onFailure_; + } else { + handler = onSuccess_; + } + if (handler != nullptr) { + handler(retCode_); + } + ret = retCode_; + return state_; +} + +RunningState SaAction::ExecuteImpl(ServiceResponseData &responseData) +{ + // execute func_ first + if (func_ != nullptr && !hasFuncExecuted_) { + retCode_ = func_(responseData, innerData_); + hasFuncExecuted_ = true; + if (retCode_ != ERR_OK) { + return RUNNING_STATE_COMPLETED; + } + } + + // check sub actions + while (!subActions_.empty()) { + curSubAction_ = std::move(subActions_.front()); + subActions_.pop_front(); + + int32_t ret = 0; + auto state = curSubAction_->Execute(ret, responseData, innerData_); + + // current sub action is paused, return. + if (state == RUNNING_STATE_PAUSED) { + return RUNNING_STATE_PAUSED; + } + + // no need to handle current sub action's result. + if (!curSubAction_->isResultAffectParent_) { + curSubAction_.reset(); + continue; + } + + // handle current sub action's result. + retCode_ = ret; + curSubAction_.reset(); + if (retCode_ != ErrorCode::NO_ERROR) { + IMSA_HILOGD("current sub action failed, drop the actions left unexecuted"); + subActions_.clear(); + } + } + + return RUNNING_STATE_COMPLETED; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/task_manager/src/actions/sa_action_wait.cpp b/services/task_manager/src/actions/sa_action_wait.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3c68a5ca22af4d00b76c8b6c003c11d154ec8ae --- /dev/null +++ b/services/task_manager/src/actions/sa_action_wait.cpp @@ -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. + */ + +#include "sa_action_wait.h" + +#include "sa_task_manager.h" + +namespace OHOS { +namespace MiscServices { +RunningState SaActionWait::Execute(int32_t &ret, ServiceResponseData &responseData) +{ + state_ = RUNNING_STATE_PAUSED; + + auto task = std::make_shared(SaTaskCode::RESUME_TIMEOUT, timeoutId_); + ret = SaTaskManager::GetInstance().PostTask(task, timeoutMs_); + return state_; +} + +RunningState SaActionWait::Execute(int32_t &ret, ServiceResponseData &responseData, ActionInnerData &innerData) +{ + return Execute(ret, responseData); +} + +RunningState SaActionWait::Resume(uint64_t resumedId, int32_t &ret, ServiceResponseData &data) +{ + if (state_ != RUNNING_STATE_PAUSED) { + return RUNNING_STATE_ERROR; + } + + if (resumedId == completeId_) { + if (onComplete_ != nullptr) { + ActionInnerData innerData; + onComplete_(data, innerData); + } + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + if (resumedId == timeoutId_) { + if (onTimeout_ != nullptr) { + ActionInnerData innerData; + onTimeout_(data, innerData); + } + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + return state_; +} + +RunningState SaActionWait::Resume( + uint64_t resumedId, int32_t &ret, ServiceResponseData &data, ActionInnerData &innerData) +{ + if (state_ != RUNNING_STATE_PAUSED) { + return RUNNING_STATE_ERROR; + } + + if (resumedId == completeId_) { + if (onComplete_ != nullptr) { + onComplete_(data, innerData); + } + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + if (resumedId == timeoutId_) { + if (onTimeout_ != nullptr) { + onTimeout_(data, innerData); + } + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + return state_; +} + +PauseInfo SaActionWait::GetPausedInfo() +{ + return pauseInfo_; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/task_manager/src/requester_manager.cpp b/services/task_manager/src/requester_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b70e25b00a78042b7a4bea06199feabdcf64569 --- /dev/null +++ b/services/task_manager/src/requester_manager.cpp @@ -0,0 +1,173 @@ +/* + * 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 "requester_manager.h" + +#include "global.h" + +namespace OHOS { +namespace MiscServices { +constexpr int32_t MAX_REQUEST_COUNT = 6; +RequesterManager &RequesterManager::GetInstance() +{ + static RequesterManager requesterManager; + return requesterManager; +} + +std::shared_ptr RequesterManager::GetRequester(int32_t pid) +{ + std::lock_guard lock(mutex_); + auto iter = requesterMap_.find(pid); + if (iter == requesterMap_.end() || iter->second == nullptr) { + IMSA_HILOGE("client: %{public}d not registered or nullptr", pid); + return nullptr; + } + if (iter->second->imaResponseChannel == nullptr && iter->second->imcResponseChannel == nullptr) { + IMSA_HILOGE("client: %{public}d channel is nullptr", pid); + return nullptr; + } + auto requesterInfo = iter->second; + if (requesterInfo->requestCount >= MAX_REQUEST_COUNT) { + IMSA_HILOGE("requests from client: %{public}d, count: %{public}d, too much", pid, requesterInfo->requestCount); + return nullptr; + } + return requesterInfo; +} + +int32_t RequesterManager::AddImaChannel(int32_t pid, sptr channel) +{ + std::lock_guard lock(mutex_); + auto iter = requesterMap_.find(pid); + if (iter != requesterMap_.end() && iter->second != nullptr) { + if (iter->second->imaResponseChannel != nullptr) { + IMSA_HILOGE("client: %{public}d already registered", pid); + return ErrorCode::NO_ERROR; + } + if (iter->second->imcResponseChannel != nullptr) { + iter->second->imaResponseChannel = channel; + IMSA_HILOGI("register success, pid: %{public}d", pid); + return ErrorCode::NO_ERROR; + } + } + + sptr deathRecipient = new (std::nothrow) InputDeathRecipient(); + if (deathRecipient == nullptr) { + IMSA_HILOGE("failed to new deathRecipient!"); + return ErrorCode::ERROR_NULL_POINTER; + } + deathRecipient->SetDeathRecipient([this, pid](const wptr &remote) { OnClientDied(pid); }); + auto object = channel->AsObject(); + if (object == nullptr || (object->IsProxyObject() && !object->AddDeathRecipient(deathRecipient))) { + IMSA_HILOGE("failed to add death recipient"); + return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED; + } + + auto info = std::make_shared(); + info->deathRecipient = deathRecipient; + info->imaResponseChannel = channel; + requesterMap_.insert_or_assign(pid, info); + IMSA_HILOGI("register success, pid: %{public}d", pid); + return ErrorCode::NO_ERROR; +} + +int32_t RequesterManager::AddImcChannel(int32_t pid, sptr channel) +{ + std::lock_guard lock(mutex_); + auto iter = requesterMap_.find(pid); + if (iter != requesterMap_.end() && iter->second != nullptr) { + if (iter->second->imcResponseChannel != nullptr) { + IMSA_HILOGE("client: %{public}d already registered", pid); + return ErrorCode::NO_ERROR; + } + if (iter->second->imaResponseChannel != nullptr) { + iter->second->imcResponseChannel = channel; + IMSA_HILOGI("register success, pid: %{public}d", pid); + return ErrorCode::NO_ERROR; + } + } + + sptr deathRecipient = new (std::nothrow) InputDeathRecipient(); + if (deathRecipient == nullptr) { + IMSA_HILOGE("failed to new deathRecipient!"); + return ErrorCode::ERROR_NULL_POINTER; + } + deathRecipient->SetDeathRecipient([this, pid](const wptr &remote) { OnClientDied(pid); }); + auto object = channel->AsObject(); + if (object == nullptr || (object->IsProxyObject() && !object->AddDeathRecipient(deathRecipient))) { + IMSA_HILOGE("failed to add death recipient"); + return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED; + } + + auto info = std::make_shared(); + info->deathRecipient = deathRecipient; + info->imcResponseChannel = channel; + requesterMap_.insert_or_assign(pid, info); + IMSA_HILOGI("register success, pid: %{public}d", pid); + return ErrorCode::NO_ERROR; +} + +void RequesterManager::TaskIn(int32_t pid) +{ + std::lock_guard lock(mutex_); + auto iter = requesterMap_.find(pid); + if (iter == requesterMap_.end()) { + IMSA_HILOGE("client: %{public}d not found", pid); + return; + } + if (iter->second == nullptr) { + IMSA_HILOGE("pid %{public}d info nullptr", pid); + return; + } + ++iter->second->requestCount; +} + +void RequesterManager::TaskOut(int32_t pid) +{ + std::lock_guard lock(mutex_); + auto iter = requesterMap_.find(pid); + if (iter == requesterMap_.end()) { + IMSA_HILOGE("client: %{public}d not found", pid); + return; + } + if (iter->second == nullptr) { + IMSA_HILOGE("pid %{public}d info nullptr", pid); + return; + } + --iter->second->requestCount; +} + +void RequesterManager::OnClientDied(int32_t pid) +{ + std::lock_guard lock(mutex_); + IMSA_HILOGI("requester: %{public}d died", pid); + auto iter = requesterMap_.find(pid); + if (iter == requesterMap_.end()) { + IMSA_HILOGD("already removed"); + return; + } + auto info = iter->second; + if (info != nullptr) { + if (info->imaResponseChannel != nullptr && info->imaResponseChannel->AsObject() != nullptr) { + info->imaResponseChannel->AsObject()->RemoveDeathRecipient(info->deathRecipient); + } + if (info->imcResponseChannel != nullptr && info->imcResponseChannel->AsObject() != nullptr) { + info->imcResponseChannel->AsObject()->RemoveDeathRecipient(info->deathRecipient); + } + } + requesterMap_.erase(pid); + IMSA_HILOGI("requester: %{public}d removed", pid); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/task_manager/src/sa_task_manager.cpp b/services/task_manager/src/sa_task_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e50336dc7a716caefd90f67f88c266f40feb04ef --- /dev/null +++ b/services/task_manager/src/sa_task_manager.cpp @@ -0,0 +1,472 @@ +/* + * 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 "sa_task_manager.h" + +#include +#include + +#include "global.h" +#include "ime_info_inquirer.h" +#include "requester_manager.h" +#include "sa_action_wait.h" +#include "xcollie/watchdog.h" + +namespace OHOS { +namespace MiscServices { +using namespace AppExecFwk; +constexpr const char *THREAD_NAME = "OS_ImsaTaskHandler"; +constexpr const uint64_t WATCHDOG_TIMEOUT = 10000; // 10S +const std::unordered_set WHITE_LIST_REQUESTS = { SaTaskCode::UPDATE_LISTEN_EVENT_FLAG }; +SaTaskManager::SaTaskManager() +{ + // initialized the event handler with 10s timeout watchdog + auto runner = EventRunner::Create(THREAD_NAME); + eventHandler_ = std::make_shared(runner); + auto ret = HiviewDFX::Watchdog::GetInstance().AddThread(THREAD_NAME, eventHandler_, nullptr, WATCHDOG_TIMEOUT); + if (ret != 0) { + IMSA_HILOGW("failed to add watch dog ret: %{public}d", ret); + } +} + +SaTaskManager &SaTaskManager::GetInstance() +{ + static SaTaskManager instance; + return instance; +} + +int32_t SaTaskManager::PostTask(SaTaskPtr task, uint32_t delayMs) +{ + if (task == nullptr) { + IMSA_HILOGE("task is nullptr"); + return ErrorCode::ERROR_NULL_POINTER; + } + auto func = [this, task]() { OnNewTask(task); }; + bool ret = eventHandler_->PostTask(func, __FUNCTION__, delayMs); + if (!ret) { + IMSA_HILOGE("failed to post task: %{public}u", static_cast(task->GetCode())); + return ErrorCode::ERROR_SA_POST_TASK_FAILED; + } + RequesterManager::GetInstance().TaskIn(task->GetCallerInfo().pid); + return ErrorCode::NO_ERROR; +} + +void SaTaskManager::ProcessAsync() +{ + auto func = [=] { Process(); }; + eventHandler_->PostTask(func, __FUNCTION__); +} + +void SaTaskManager::Complete(uint64_t resumeId) +{ + PostTask(std::make_shared(SaTaskCode::RESUME_WAIT, resumeId)); +} + +int32_t SaTaskManager::Pend(SaActionPtr action) +{ + if (action == nullptr) { + IMSA_HILOGE("action is nullptr"); + return ErrorCode::ERROR_NULL_POINTER; + } + if (curTask_ == nullptr || !curTask_->IsRunning()) { + IMSA_HILOGE("curTask_ is NULL or not running, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + return curTask_->Pend(std::move(action)); +} + +int32_t SaTaskManager::Pend(const SaActionFunc &func) +{ + return Pend(std::make_unique(func)); +} + +int32_t SaTaskManager::PendWaitResult(const SaActionFunc &func) +{ + if (curTask_ == nullptr || !curTask_->IsPaused()) { + IMSA_HILOGE("curTask_ is NULL or not paused, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + auto action = std::make_unique(func); + return curTask_->Pend(std::move(action)); +} + +int32_t SaTaskManager::WaitExec(std::unique_ptr waitAction, SaActionFunc execFunc) +{ + if (waitAction == nullptr) { + IMSA_HILOGE("wait action nullptr"); + return ErrorCode::ERROR_IMSA_NULLPTR; + } + int32_t ret = Pend(std::move(waitAction)); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Pend ActionWait failed, ret: %{public}d", ret); + return ret; + } + + auto exec = std::make_unique(execFunc); + ret = Pend(std::move(execFunc)); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Pend Action failed, ret=%{public}d", ret); + return ret; + } + return ErrorCode::NO_ERROR; +} + +void SaTaskManager::SetInited(bool flag) +{ + inited_ = flag; +} + +void SaTaskManager::OnNewTask(SaTaskPtr task) +{ + if (task == nullptr) { + IMSA_HILOGE("task is nullptr"); + return; + } + auto taskType = task->GetType(); + if (taskType <= SaTaskType::TYPE_INVALID || taskType >= SaTaskType::TYPE_TOTAL_COUNT) { + IMSA_HILOGE("task type %{public}d unknown!", taskType); + return; + } + switch (taskType) { + case SaTaskType::TYPE_CRITICAL_CHANGE: { + criticalTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_SWITCH_IME: { + switchImeTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_HIGHER_REQUEST: { + higherRequestTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_NORMAL_REQUEST: { + normalRequestTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_QUERY: { + queryTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_RESUME: { + resumeTasks_.push_back(task); + break; + } + case SaTaskType::TYPE_INNER: { + innerTasks_.push_back(task); + break; + } + default: { + IMSA_HILOGE("task type %{public}d unknown!", taskType); + return; + } + } + + Process(); +} + +void SaTaskManager::Process() +{ + // tasks creating resume inner tasks + ProcessNextResumeTask(); + // tasks acting on the current paused task + ProcessNextInnerTask(); + + // tasks bringing critical changes or updates + ProcessNextCriticalTask(); + // tasks causing ime switch + ProcessNextSwitchImeTask(); + + // tasks with a higher priority request + ProcessNextHigherRequestTask(); + // tasks with a normal priority request + ProcessNextNormalRequestTask(); + + // tasks used for querying + ProcessNextQueryTask(); +} + +void SaTaskManager::ProcessNextCriticalTask() +{ + if (criticalTasks_.empty()) { + return; + } + // CRITICAL_CHANGE task has the highest priority. If curTask_ exists and is not CRITICAL_CHANGE task, drop it. + if (curTask_ != nullptr) { + if (curTask_->GetType() == SaTaskType::TYPE_CRITICAL_CHANGE && curTask_->IsPaused()) { + return; + } + curTask_.reset(); + } + + while (curTask_ == nullptr) { + if (criticalTasks_.empty()) { + return; + } + curTask_ = criticalTasks_.front(); + criticalTasks_.pop_front(); + ExecuteCurrentTask(); + } +} + +void SaTaskManager::ProcessNextSwitchImeTask() +{ + if (switchImeTasks_.empty()) { + return; + } + // SWITCH_IME task has a priority second to type CRITICAL_CHANGE. + if (curTask_ != nullptr) { + if (curTask_->IsPaused()) { + return; + } + IMSA_HILOGW("curTask_ state abnormal! Reset"); + curTask_.reset(); + } + + while (curTask_ == nullptr) { + if (switchImeTasks_.empty()) { + return; + } + curTask_ = switchImeTasks_.front(); + switchImeTasks_.pop_front(); + ExecuteCurrentTask(); + } +} + +void SaTaskManager::ProcessNextHigherRequestTask() +{ + if (!inited_) { + IMSA_HILOGW("not initialized yet"); + return; + } + if (higherRequestTasks_.empty()) { + IMSA_HILOGD("immeRequestTasks_ empty"); + return; + } + + // If curTask_ is NULL or state abnormal, execute higherRequestTasks_ directly. + if (curTask_ == nullptr || !curTask_->IsPaused()) { + curTask_.reset(); + while (!higherRequestTasks_.empty() && curTask_ == nullptr) { + curTask_ = higherRequestTasks_.front(); + higherRequestTasks_.pop_front(); + ExecuteCurrentTask(); + } + return; + } + + // If curTask_ not NULL, task which comes from target app and is in white list can be executed. + pausedTask_ = std::move(curTask_); + std::list remainingTasks; + while (!higherRequestTasks_.empty()) { + auto task = higherRequestTasks_.front(); + higherRequestTasks_.pop_front(); + // Task not from target app, keep waiting. + if (pausedTask_->GetPauseInfo().target != task->GetCallerInfo().bundleName) { + remainingTasks.push_back(task); + continue; + } + // Task from target app but not in whitelist, reject directly. + if (!IsWhiteListRequest(task->GetCode())) { + task->OnResponse(ErrorCode::ERROR_IMSA_TASK_TIMEOUT); + continue; + } + // Task from target app and in white list, execute it. + curTask_ = task; + ExecuteCurrentTask(); + } + // Restore curTask_ with pausedTask, restore immeRequestTasks_ with tasks still waiting. + curTask_ = std::move(pausedTask_); + higherRequestTasks_ = std::move(remainingTasks); +} + +void SaTaskManager::ProcessNextNormalRequestTask() +{ + if (!inited_) { + IMSA_HILOGW("not initialized yet"); + return; + } + if (normalRequestTasks_.empty()) { + IMSA_HILOGD("requestTasks_ empty"); + return; + } + + // If curTask_ is NULL or state abnormal, execute normalRequestTasks_ directly. + if (curTask_ == nullptr || !curTask_->IsPaused()) { + while (!normalRequestTasks_.empty() && curTask_ == nullptr) { + curTask_ = normalRequestTasks_.front(); + normalRequestTasks_.pop_front(); + ExecuteCurrentTask(); + } + return; + } + + // If curTask_ not NULL, task which is from target app and in white list can be executed. + pausedTask_ = std::move(curTask_); + std::list remainingTask; + while (!normalRequestTasks_.empty()) { + auto task = normalRequestTasks_.front(); + normalRequestTasks_.pop_front(); + // Task not from target app, keep waiting. + if (pausedTask_->GetPauseInfo().target != task->GetCallerInfo().bundleName) { + remainingTask.push_back(task); + continue; + } + // Task from target app but not in whitelist, reject it. + if (!IsWhiteListRequest(task->GetCode())) { + task->OnResponse(ErrorCode::ERROR_IMSA_TASK_TIMEOUT); + continue; + } + // Task from target app and in white list, execute it. + curTask_ = task; + ExecuteCurrentTask(); + } + // Restore curTask_ with pausedTask, restore normalRequestTasks_ with tasks still waiting. + curTask_ = std::move(pausedTask_); + normalRequestTasks_ = std::move(remainingTask); +} + +void SaTaskManager::ProcessNextQueryTask() +{ + if (!inited_) { + IMSA_HILOGW("not initialized yet"); + return; + } + if (queryTasks_.empty()) { + IMSA_HILOGD("queryTasks_ empty"); + return; + } + // QUERY tasks can be executed when curTask_ exists. + auto pausedTask = std::move(curTask_); + while (curTask_ == nullptr && !queryTasks_.empty()) { + curTask_ = queryTasks_.front(); + queryTasks_.pop_front(); + ExecuteCurrentTask(); + } + curTask_ = std::move(pausedTask); +} + +void SaTaskManager::ProcessNextResumeTask() +{ + if (resumeTasks_.empty()) { + IMSA_HILOGD("resumeTasks_ empty, return"); + return; + } + // RESUME tasks can be executed when curTask_ exists. + pausedTask_ = std::move(curTask_); + while (curTask_ == nullptr && !resumeTasks_.empty()) { + curTask_ = resumeTasks_.front(); + resumeTasks_.pop_front(); + ExecuteCurrentTask(); + } + curTask_ = std::move(pausedTask_); +} + +void SaTaskManager::ProcessNextInnerTask() +{ + while (curTask_ != nullptr) { + // curTask_ is not NULL, it must be paused + // Loop through innerTasks_, try resume + if (innerTasks_.empty()) { + IMSA_HILOGD("innerTasks_ empty, return"); + return; + } + + auto task = innerTasks_.front(); + innerTasks_.pop_front(); + auto state = curTask_->OnTask(task); + if (state == RUNNING_STATE_COMPLETED) { + // current task completed + curTask_.reset(); + innerTasks_.clear(); + return; + } + + if (state == RUNNING_STATE_PAUSED) { + // current task still paused, try next inner task + continue; + } + + // unreachable + IMSA_HILOGE("Unexpected OnTask result %{public}d", state); + curTask_.reset(); + innerTasks_.clear(); + } +} + +void SaTaskManager::ExecuteCurrentTask() +{ + if (curTask_ == nullptr) { + return; + } + auto state = curTask_->Execute(); + if (state == RUNNING_STATE_COMPLETED) { + IMSA_HILOGI("curTask_ %{public}u completed", static_cast(curTask_->GetCode())); + RequesterManager::GetInstance().TaskOut(curTask_->GetCallerInfo().pid); + curTask_.reset(); + ProcessAsync(); + return; + } + if (state == RUNNING_STATE_PAUSED) { + IMSA_HILOGI("curTask_ %{public}u paused", static_cast(curTask_->GetCode())); + return; + } + IMSA_HILOGE("Unexpected execute result state: %{public}u", state); + RequesterManager::GetInstance().TaskOut(curTask_->GetCallerInfo().pid); + curTask_.reset(); +} + +void SaTaskManager::TryResume(const PauseType &pauseType, const CallerInfo &callerInfo) +{ + if (pausedTask_ == nullptr || !pausedTask_->IsPaused()) { + IMSA_HILOGD("curTask_ nullptr or not paused state"); + return; + } + PauseInfo pausedInfo = pausedTask_->GetPauseInfo(); + if (pausedInfo.type == PauseType::PAUSED_TYPE_INVALID) { + IMSA_HILOGE("invalid pause type"); + return; + } + if (pauseType != pausedInfo.type) { + IMSA_HILOGD("type not match, type: %{public}d, target: %{public}d", static_cast(pauseType), + static_cast(pausedInfo.type)); + return; + } + if (callerInfo.bundleName != pausedInfo.target) { + IMSA_HILOGD("bundleName not match, caller: %{public}s, target: %{public}s", callerInfo.bundleName.c_str(), + pausedInfo.target.c_str()); + return; + } + IMSA_HILOGI("start resume, %{public}s", pausedInfo.ToString().c_str()); + Complete(pausedInfo.resumeId); +} + +void SaTaskManager::Reset() +{ + inited_ = false; + curTask_ = nullptr; + eventHandler_ = nullptr; + innerTasks_.clear(); + criticalTasks_.clear(); + normalRequestTasks_.clear(); + queryTasks_.clear(); +} + +bool SaTaskManager::IsWhiteListRequest(SaTaskCode taskCode) +{ + return WHITE_LIST_REQUESTS.find(taskCode) != WHITE_LIST_REQUESTS.end(); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/task_manager/src/tasks/sa_task.cpp b/services/task_manager/src/tasks/sa_task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71d49fbcaddee0ed49c5b6cff647c9bb450611bb --- /dev/null +++ b/services/task_manager/src/tasks/sa_task.cpp @@ -0,0 +1,230 @@ +/* + * 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 "sa_task.h" + +#include + +namespace OHOS { +namespace MiscServices { +SaTask::~SaTask() +{ + if (!hasResponded_) { + failRet_ = ErrorCode::ERROR_IMSA_TASK_TIMEOUT; + InvokeResponse(); + } +} + +RunningState SaTask::Execute() +{ + if (state_ != RUNNING_STATE_IDLE) { + IMSA_HILOGE("Task not runnable, state=%{public}u", state_); + return RUNNING_STATE_ERROR; + } + return ExecuteInner(); +} + +RunningState SaTask::Resume(uint64_t resumeId) +{ + if (action_ == nullptr) { + IMSA_HILOGE("curAction_ is nullptr"); + return RUNNING_STATE_ERROR; + } + + if (state_ != RUNNING_STATE_PAUSED) { + IMSA_HILOGE("state_ is %{public}u, do not need to resume", state_); + return RUNNING_STATE_ERROR; + } + + int32_t ret = 0; + auto state = action_->Resume(resumeId, ret, responseData_); + if (state == RUNNING_STATE_PAUSED) { + return state_; + } + if (state == RUNNING_STATE_COMPLETED) { + state_ = RUNNING_STATE_COMPLETED; + IMSA_HILOGE("curAction_ complete!"); + return state_; + } + IMSA_HILOGE("curAction_ resume return %{public}u, error!", state); + return RUNNING_STATE_ERROR; +} + +RunningState SaTask::OnTask(const std::shared_ptr &task) +{ + if (task == nullptr) { + IMSA_HILOGE("task is nullptr"); + return state_; + } + auto type = task->GetType(); + if (type == SaTaskType::TYPE_INNER) { + return Resume(task->GetSeqId()); + } + return state_; +} + +int32_t SaTask::PendSingle(std::unique_ptr action) +{ + if (action_ == nullptr || action_->GetState() != RUNNING_STATE_RUNNING) { + IMSA_HILOGE("curAction_ is NULL or not running, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + return action_->Pend(std::move(action)); +} + +int32_t SaTask::PendSingle(SaActionFunc func) +{ + if (action_ == nullptr || action_->GetState() != RUNNING_STATE_RUNNING) { + IMSA_HILOGE("curAction_ is NULL or not running, pend failed!"); + return ErrorCode::ERROR_SA_TASK_MANAGER_PEND_ACTION_FAILED; + } + return action_->Pend(std::make_unique(func)); +} + +SaTaskType SaTask::GetType() const +{ + auto type = static_cast(code_); + if (type >= static_cast(SaTaskCode::TASK_CRITICAL_CHANGE_BEGIN) + && type <= static_cast(SaTaskCode::TASK_CRITICAL_CHANGE_END)) { + return SaTaskType::TYPE_CRITICAL_CHANGE; + } + if (type >= static_cast(SaTaskCode::TASK_SWITCH_IME_BEGIN) + && type <= static_cast(SaTaskCode::TASK_SWITCH_IME_END)) { + return SaTaskType::TYPE_SWITCH_IME; + } + if (type >= static_cast(SaTaskCode::TASK_HIGHER_REQUEST_BEGIN) + && type <= static_cast(SaTaskCode::TASK_HIGHER_REQUEST_END)) { + return SaTaskType::TYPE_HIGHER_REQUEST; + } + if (type >= static_cast(SaTaskCode::TASK_NORMAL_REQUEST_BEGIN) + && type <= static_cast(SaTaskCode::TASK_NORMAL_REQUEST_END)) { + return SaTaskType::TYPE_NORMAL_REQUEST; + } + if (type >= static_cast(SaTaskCode::TASK_QUERY_BEGIN) + && type <= static_cast(SaTaskCode::TASK_QUERY_END)) { + return SaTaskType::TYPE_QUERY; + } + if (type >= static_cast(SaTaskCode::TASK_RESUME_BEGIN) + && type <= static_cast(SaTaskCode::TASK_RESUME_END)) { + return SaTaskType::TYPE_RESUME; + } + if (type >= static_cast(SaTaskCode::TASK_INNER_BEGIN) + && type <= static_cast(SaTaskCode::TASK_INNER_END)) { + return SaTaskType::TYPE_INNER; + } + return SaTaskType::TYPE_INVALID; +} + +SaTaskCode SaTask::GetCode() const +{ + return code_; +} + +uint64_t SaTask::GetSeqId() const +{ + return seqId_; +} + +CallerInfo SaTask::GetCallerInfo() const +{ + return callerInfo_; +} + +bool SaTask::IsRunning() const +{ + return state_ == RUNNING_STATE_RUNNING; +} + +bool SaTask::IsPaused() const +{ + return state_ == RUNNING_STATE_PAUSED; +} + +uint64_t SaTask::GetNextSeqId() +{ + static std::atomic seqId{ 1 }; + return seqId.fetch_add(1, std::memory_order_seq_cst); +} + +void SaTask::SetHiSysReporter(const ReportFunc &func) +{ + hiSysReporter_ = std::make_unique(func); +} + +RunningState SaTask::ExecuteInner() +{ + state_ = RUNNING_STATE_RUNNING; + if (action_ == nullptr) { + IMSA_HILOGW("action_ is nullptr"); + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + RunningState state = action_->Execute(retCode_, responseData_); + if (state == RUNNING_STATE_COMPLETED) { + InvokeResponse(); + state_ = RUNNING_STATE_COMPLETED; + return state_; + } + + state_ = RUNNING_STATE_PAUSED; + return state_; +} + +void SaTask::OnResponse(int32_t retCode) +{ + retCode_ = retCode; + InvokeResponse(); +} + +void SaTask::InvokeResponse() +{ + hasResponded_ = true; + + if (retCode_ != ErrorCode::NO_ERROR) { + // When failRect_ is set validly, return failRet_. + if (failRet_ != INVALID_FAIL_CODE) { + retCode_ = failRet_; + } + } + + if (hiSysReporter_ != nullptr) { + hiSysReporter_->Execute(retCode_, responseData_); + } + + if (imaResponseChannel_ != nullptr) { + ServiceResponseDataInner inner; + inner.data = responseData_; + imaResponseChannel_->OnResponse(callerInfo_.requestId, retCode_, inner); + } + if (imcResponseChannel_ != nullptr) { + ServiceResponseDataInner inner; + inner.data = responseData_; + imaResponseChannel_->OnResponse(callerInfo_.requestId, retCode_, inner); + } + + action_ = nullptr; +} + +PauseInfo SaTask::GetPauseInfo() +{ + if (action_ == nullptr || action_->GetState() != RUNNING_STATE_PAUSED) { + IMSA_HILOGE("curAction_ nullptr or not paused"); + return {}; + } + return action_->GetPausedInfo(); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/test/fuzztest/commonevent_fuzzer/commonevent_fuzzer.cpp b/test/fuzztest/commonevent_fuzzer/commonevent_fuzzer.cpp index bcf43d62fe13af333f8fc74aae8e58f4be00dcc4..d9e982c96366acf9df7ae645ad476ccda561994c 100644 --- a/test/fuzztest/commonevent_fuzzer/commonevent_fuzzer.cpp +++ b/test/fuzztest/commonevent_fuzzer/commonevent_fuzzer.cpp @@ -33,7 +33,6 @@ #include "system_cmd_channel_service_impl.h" using namespace OHOS::MiscServices; -using namespace MessageID; namespace OHOS { uint32_t ConvertToUint32(const uint8_t *ptr) { diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 7669e6f73c6d6eea600a3f12465d23372d44bb5b..699b6a45bf52f60e69eb42e6f1eb93ea898c051b 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -46,6 +46,7 @@ group("unittest") { "cpp_test:JsonOperateTest", "cpp_test:NewImeSwitchTest", "cpp_test:NumKeyAppsManagerTest", + "cpp_test:SaTaskManagerTest", "cpp_test:OnDemandStartStopSaTest", "cpp_test:StringUtilsTest", "cpp_test:TaskManagerTest", diff --git a/test/unittest/cpp_test/BUILD.gn b/test/unittest/cpp_test/BUILD.gn index c9f8858c87f57d156c452277c336f91799740377..21cee6bd82dea44a76c4bbb64a171bdad58d9220 100644 --- a/test/unittest/cpp_test/BUILD.gn +++ b/test/unittest/cpp_test/BUILD.gn @@ -1615,6 +1615,53 @@ ohos_unittest("NumKeyAppsManagerTest") { ] } +ohos_unittest("SaTaskManagerTest") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + module_out_path = module_output_path + include_dirs = [ "${inputmethod_path}/common/include" ] + sources = [ + "src/sa_task_manager_test.cpp", + "${inputmethod_path}/services/task_manager/src/requester_manager.cpp", + "${inputmethod_path}/services/task_manager/src/sa_task_manager.cpp", + "${inputmethod_path}/services/task_manager/src/actions/sa_action.cpp", + "${inputmethod_path}/services/task_manager/src/actions/sa_action_wait.cpp", + "${inputmethod_path}/services/task_manager/src/tasks/sa_task.cpp", + ] + + configs = [ ":module_private_config" ] + deps = [ + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client_static", + "${inputmethod_path}/services:inputmethod_service_static", + "${inputmethod_path}/services/adapter/settings_data_provider:settings_data_static", + "${inputmethod_path}/services/file:imf_file_static", + "${inputmethod_path}/services/json:imf_json_static", + "${inputmethod_path}/test/unittest/cpp_test/common:inputmethod_tdd_util", + "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:ima_response_channel_proxy", + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:imc_response_channel_proxy", + + ] + + external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "config_policy:configpolicy_util", + "data_share:datashare_common", + "data_share:datashare_consumer", + "googletest:gtest_main", + "hilog:libhilog", + "init:libbeget_proxy", + "init:libbegetutil", + "input:libmmi-client", + "resource_management:global_resmgr", + ] +} + ohos_unittest("ImaTextEditTest") { branch_protector_ret = "pac_ret" sanitize = { diff --git a/test/unittest/cpp_test/src/response_data_test.cpp b/test/unittest/cpp_test/src/response_data_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54fe068a0e5b0c8820448513c2896c56d67f7b93 --- /dev/null +++ b/test/unittest/cpp_test/src/response_data_test.cpp @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#define private public +#define protected public +#include "response_data_util.h" +#include "service_response_data.h" +#undef private + +#include +#include + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace MiscServices { +class ResponseDataTest : public testing::Test { +public: + static void SetUpTestCase() + { + } + static void TearDownTestCase() + { + } + void SetUp() + { + } + void TearDown() + { + } + + template static ServiceValueType GetServiceDataTypeIndex() + { + auto index = std::variant_alternative_t<0, ServiceResponseData> == std::monostate + ? std::variant::template index_of - 1 + : std::variant::template index_of; + return static_cast(index); + } +}; + +/** + * @tc.name: ServiceResponseDataTypeValueTest + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(ResponseDataTest, ServiceResponseDataTypeTest, TestSize.Level0) +{ + // test basic type + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_BOOL); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_INT32); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_UINT32); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_INT64); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_UINT64); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex>(), ServiceValueType::TYPE_REMOTE_OBJECT); + + // test inner type + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_PROPERTY); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex>(), ServiceValueType::TYPE_PROPERTIES); + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_SUB_PROPERTY); + EXPECT_EQ( + ResponseDataTest::GetServiceDataTypeIndex>(), ServiceValueType::TYPE_SUB_PROPERTIES); + EXPECT_EQ( + ResponseDataTest::GetServiceDataTypeIndex(), ServiceValueType::TYPE_START_INPUT_RESPONSE); + + // test external type + EXPECT_EQ(ResponseDataTest::GetServiceDataTypeIndex>(), + ServiceValueType::TYPE_AMS_ELEMENT_NAME); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cpp_test/src/sa_task_manager_test.cpp b/test/unittest/cpp_test/src/sa_task_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2eb5bd4feabb15213191501a110e00d5b06e8f82 --- /dev/null +++ b/test/unittest/cpp_test/src/sa_task_manager_test.cpp @@ -0,0 +1,692 @@ +/* + * 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. + */ + +#define private public +#define protected public +#include "sa_task_manager.h" + +#include "response_data_util.h" +#include "service_response_data.h" +#undef private + +#include +#include +#include + +#include +#include + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace MiscServices { +constexpr uint32_t PAUSE_TIMEOUT = 100; // 100ms +constexpr uint32_t DELAY_TIME = 200; // 200ms +constexpr uint32_t SUCCESS_RESULT = 100; +constexpr uint32_t FAILED_RESULT = 999; +constexpr uint32_t WAIT_EXEC_END = 50000; // 50ms +constexpr uint32_t WAIT_PAUSE_EXEC_END = 500000; // 500ms +class SaTaskManagerTest : public testing::Test { +public: + static void SetUpTestCase() + { + IMSA_HILOGI("SaTaskManagerTest::SetUpTestCase"); + SaTaskManager::GetInstance(); + } + static void TearDownTestCase() + { + IMSA_HILOGI("SaTaskManagerTest::TearDownTestCase"); + } + void SetUp() + { + IMSA_HILOGI("SaTaskManagerTest::SetUp"); + SaTaskManagerTest::result_ = 0; + } + void TearDown() + { + IMSA_HILOGI("SaTaskManagerTest::TearDown"); + SaTaskManagerTest::result_ = 0; + } + + static bool TestSamePriorityTaskOrdering(SaTaskCode codeTypeBegin); + static bool TestSameInterrupt(SaTaskCode codeTypeBegin, bool isPauseTimeout); + static bool TestLowInterruptHigh(SaTaskCode higherTaskCode, SaTaskCode lowerTaskCode, bool isPauseTimeout); + static bool TestHighInterruptLow(SaTaskCode higherTaskCode, SaTaskCode lowerTaskCode, bool isPauseTimeout); + + static bool TestPauseAndExec(SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout); + static bool TestPauseAndExecWhiteListRequest( + SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout); + static bool TestPauseAndExecNonWhiteListRequest( + SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout); + + static void SetResult(uint32_t result); + static uint32_t GetResult(); + static int32_t StartPause(const PauseInfo &info, uint32_t timeoutMs); + static std::mutex mtx_; + static uint32_t result_; +}; +uint32_t SaTaskManagerTest::result_{ 0 }; +std::mutex SaTaskManagerTest::mtx_{}; + +bool SaTaskManagerTest::TestSamePriorityTaskOrdering(SaTaskCode codeTypeBegin) +{ + result_ = 1; + uint32_t taskCode1 = static_cast(codeTypeBegin) + 1; + uint32_t taskCode2 = static_cast(codeTypeBegin) + 2; + IMSA_HILOGI("taskCode1: %{public}u, taskCode2: %{public}u", taskCode1, taskCode2); + auto action1 = [](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec task1 start"); + result_ += 5; + IMSA_HILOGI("exec task1 end"); + return ErrorCode::NO_ERROR; + }; + auto task1 = std::make_shared(static_cast(taskCode1), action1); + auto action2 = [](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec task2 start"); + result_ *= 2; + IMSA_HILOGI("exec task2 end"); + return ErrorCode::NO_ERROR; + }; + auto task2 = std::make_shared(static_cast(taskCode2), action2); + SaTaskManager::GetInstance().PostTask(task1); + SaTaskManager::GetInstance().PostTask(task2); + usleep(WAIT_EXEC_END); + return result_ == 12; // (1 + 5) * 2 = 12 +} + +bool SaTaskManagerTest::TestSameInterrupt(SaTaskCode codeTypeBegin, bool isPauseTimeout) +{ + result_ = 0; + uint32_t taskCode1 = static_cast(codeTypeBegin) + 1; + uint32_t taskCode2 = static_cast(codeTypeBegin) + 2; + IMSA_HILOGI("taskCode1: %{public}u, taskCode2: %{public}u", taskCode1, taskCode2); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestLowInterruptHigh" }; + auto action1 = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + result_ += 1; + IMSA_HILOGI("exec task1 start"); + return StartPause(info, PAUSE_TIMEOUT); + }; + auto task1 = std::make_shared(static_cast(taskCode1), action1); + + auto action2 = [](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec task2 start"); + result_ *= 2; + IMSA_HILOGI("exec task2 end"); + return ErrorCode::NO_ERROR; + }; + auto task2 = std::make_shared(static_cast(taskCode2), action2); + + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + SaTaskManager::GetInstance().PostTask(task1); + SaTaskManager::GetInstance().PostTask(task2); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + usleep(WAIT_PAUSE_EXEC_END); + uint32_t expectValue = 0; + if (isPauseTimeout) { + expectValue = (1 + FAILED_RESULT) * 2; + } else { + expectValue = (1 + SUCCESS_RESULT) * 2; + } + return result_ == expectValue; +} + +bool SaTaskManagerTest::TestLowInterruptHigh(SaTaskCode higherTaskCode, SaTaskCode lowerTaskCode, bool isPauseTimeout) +{ + result_ = 0; + IMSA_HILOGI("higherTaskCode: %{public}u, lowerTaskCode: %{public}u", static_cast(higherTaskCode), + static_cast(lowerTaskCode)); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestLowInterruptHigh" }; + // create higher task + auto higherAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + result_ += 1; + IMSA_HILOGI("exec higherTask start"); + return StartPause(info, PAUSE_TIMEOUT); + }; + auto higherTask = std::make_shared(higherTaskCode, higherAction); + + // create lower task + auto lowerAction = [](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec lowerTask start"); + result_ *= 2; + IMSA_HILOGI("exec lowerTask end"); + return ErrorCode::NO_ERROR; + }; + auto lowerTask = std::make_shared(lowerTaskCode, lowerAction); + + // create higher task's resume task + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + + // post order: higherTask -> lowerTask -> resumeTask + SaTaskManager::GetInstance().PostTask(higherTask); + SaTaskManager::GetInstance().PostTask(lowerTask); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + + // expect exec order: higherTask -> resumeTask -> lowerTask + uint32_t expectValue = 0; + if (isPauseTimeout) { + expectValue = (1 + FAILED_RESULT) * 2; + } else { + expectValue = (1 + SUCCESS_RESULT) * 2; + } + usleep(WAIT_PAUSE_EXEC_END); + return result_ == expectValue; +} + +bool SaTaskManagerTest::TestHighInterruptLow(SaTaskCode higherTaskCode, SaTaskCode lowerTaskCode, bool isPauseTimeout) +{ + result_ = 0; + IMSA_HILOGI("higherTaskCode: %{public}u, lowerTaskCode: %{public}u", static_cast(higherTaskCode), + static_cast(lowerTaskCode)); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestLowInterruptHigh" }; + auto lowerAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + result_ += 1; + IMSA_HILOGI("exec lowerTask start"); + return StartPause(info, PAUSE_TIMEOUT); + }; + auto lowerTask = std::make_shared(static_cast(lowerTaskCode), lowerAction); + + auto higherAction = [](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec higherTask start"); + result_ *= 2; + IMSA_HILOGI("exec higherTask end"); + return ErrorCode::NO_ERROR; + }; + auto higherTask = std::make_shared(static_cast(higherTaskCode), higherAction); + + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + + // post order: lowerTask -> higherTask -> resumeTask + SaTaskManager::GetInstance().PostTask(lowerTask); + SaTaskManager::GetInstance().PostTask(higherTask); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + + // expect exec order: lowerTask -> higherTask + uint32_t expectValue = 1 * 2; + usleep(WAIT_PAUSE_EXEC_END); + return result_ == expectValue; +} + +bool SaTaskManagerTest::TestPauseAndExec(SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout) +{ + result_ = 0; + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute001 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestPostTask006" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseTask start"); + SaTaskManagerTest::result_ = 1; + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(pausedTaskCode, pauseAction); + + auto newAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec newTask start"); + SaTaskManagerTest::result_ *= 2; + IMSA_HILOGI("exec newTask end"); + return ErrorCode::NO_ERROR; + }; + auto newTask = std::make_shared(newTaskCode, newAction); + + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(newTask); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + + uint32_t expectedValue = 0; + if (isPauseTimeout) { + expectedValue = (1 * 2) + FAILED_RESULT; + } else { + expectedValue = (1 * 2) + SUCCESS_RESULT; + } + usleep(WAIT_PAUSE_EXEC_END); + return result_ == expectedValue; +} + +bool SaTaskManagerTest::TestPauseAndExecWhiteListRequest( + SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout) +{ + result_ = 0; + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute001 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestPostTask006" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseTask start"); + SaTaskManagerTest::result_ = 1; + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(pausedTaskCode, pauseAction); + + auto newAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec newTask start"); + SaTaskManagerTest::result_ *= 2; + IMSA_HILOGI("exec newTask end"); + return ErrorCode::NO_ERROR; + }; + CallerInfo callerInfo = { .bundleName = info.target }; + auto newTask = std::make_shared(newTaskCode, newAction, callerInfo); + + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(newTask); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + + uint32_t expectedValue = 0; + if (isPauseTimeout) { + expectedValue = (1 * 2) + FAILED_RESULT; + } else { + expectedValue = (1 * 2) + SUCCESS_RESULT; + } + usleep(WAIT_PAUSE_EXEC_END); + return result_ == expectedValue; +} + +bool SaTaskManagerTest::TestPauseAndExecNonWhiteListRequest( + SaTaskCode pausedTaskCode, SaTaskCode newTaskCode, bool isPauseTimeout) +{ + result_ = 0; + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute001 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "targetBundleName" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseTask start"); + SaTaskManagerTest::result_ = 1; + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(pausedTaskCode, pauseAction); + + auto newAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec newTask start"); + SaTaskManagerTest::result_ *= 2; + IMSA_HILOGI("exec newTask end"); + return ErrorCode::NO_ERROR; + }; + CallerInfo callerInfo = { .bundleName = info.target }; + auto newTask = std::make_shared(newTaskCode, newAction, callerInfo); + + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeTask start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(info.type, callerInfo); + IMSA_HILOGI("exec resumeTask end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(newTask); + if (isPauseTimeout) { + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + } else { + SaTaskManager::GetInstance().PostTask(resumeTask); + } + + uint32_t expectedValue = 0; + if (isPauseTimeout) { + expectedValue = 1 + FAILED_RESULT; + } else { + expectedValue = 1 + SUCCESS_RESULT; + } + usleep(WAIT_PAUSE_EXEC_END); + return result_ == expectedValue; +} + +void SaTaskManagerTest::SetResult(uint32_t result) +{ + std::lock_guard lock(mtx_); + result_ = result; + IMSA_HILOGI("result: %{public}u", result_); +} + +uint32_t SaTaskManagerTest::GetResult() +{ + std::lock_guard lock(mtx_); + IMSA_HILOGI("result: %{public}u", result_); + return result_; +} + +int32_t SaTaskManagerTest::StartPause(const PauseInfo &info, uint32_t timeoutMs) +{ + SaActionFunc onComplete = [](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGI("onComplete"); + result_ += SUCCESS_RESULT; + return ErrorCode::NO_ERROR; + }; + SaActionFunc onTimeout = [](ServiceResponseData &, ActionInnerData &) { + IMSA_HILOGI("onTimeout"); + result_ += FAILED_RESULT; + return ErrorCode::ERROR_IMSA_IME_START_TIMEOUT; + }; + auto waitAction = std::make_unique(timeoutMs, info, onComplete, onTimeout); + return SaTaskManager::GetInstance().WaitExec(std::move(waitAction)); +} + +/** + * @tc.name: TestSamePriorityOrdering + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestSamePriorityOrdering, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestSamePriorityOrdering START"); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_CRITICAL_CHANGE_BEGIN)); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_SWITCH_IME_BEGIN)); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_HIGHER_REQUEST_BEGIN)); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_NORMAL_REQUEST_BEGIN)); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_QUERY_BEGIN)); + EXPECT_TRUE(TestSamePriorityTaskOrdering(SaTaskCode::TASK_RESUME_BEGIN)); +} + +/** + * @tc.name: TestPauseAndResume001 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndResume001, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndResume001 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestPostTask001" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseAction start"); + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(SaTaskCode::SWITCH_INPUT_METHOD, pauseAction); + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeAction start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(PauseType::PAUSE_TYPE_START_IME, callerInfo); + IMSA_HILOGI("exec resumeAction end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(resumeTask); + usleep(WAIT_PAUSE_EXEC_END); + EXPECT_EQ(SaTaskManagerTest::GetResult(), SUCCESS_RESULT); +} + +/** + * @tc.name: TestPauseAndResume002 + * @tc.desc: resume timeout + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndResume002, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndResume002 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestPostTask001" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseAction start"); + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(SaTaskCode::SWITCH_INPUT_METHOD, pauseAction); + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeAction start"); + CallerInfo callerInfo = { .bundleName = info.target }; + SaTaskManager::GetInstance().TryResume(PauseType::PAUSE_TYPE_START_IME, callerInfo); + IMSA_HILOGI("exec resumeAction end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(resumeTask, DELAY_TIME); + usleep(WAIT_PAUSE_EXEC_END); + EXPECT_EQ(SaTaskManagerTest::GetResult(), FAILED_RESULT); +} + +/** + * @tc.name: TestPauseAndResume003 + * @tc.desc: resume failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndResume003, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndResume003 START"); + PauseInfo info = { .type = PauseType::PAUSE_TYPE_START_IME, .target = "TestPostTask001" }; + auto pauseAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec pauseAction start"); + return SaTaskManagerTest::StartPause(info, PAUSE_TIMEOUT); + }; + auto pauseTask = std::make_shared(SaTaskCode::SWITCH_INPUT_METHOD, pauseAction); + auto resumeAction = [info](ServiceResponseData &, ActionInnerData &) -> int32_t { + IMSA_HILOGI("exec resumeAction start"); + CallerInfo callerInfo = { .bundleName = "invalidValue" }; + SaTaskManager::GetInstance().TryResume(PauseType::PAUSE_TYPE_START_IME, callerInfo); + IMSA_HILOGI("exec resumeAction end"); + return ErrorCode::NO_ERROR; + }; + auto resumeTask = std::make_shared(SaTaskCode::SET_CORE_AND_AGENT, resumeAction); + SaTaskManager::GetInstance().PostTask(pauseTask); + SaTaskManager::GetInstance().PostTask(resumeTask); + usleep(WAIT_PAUSE_EXEC_END); + EXPECT_EQ(SaTaskManagerTest::GetResult(), FAILED_RESULT); +} + +/** + * @tc.name: TestPauseAndInterrupt001 + * @tc.desc: Same priority can not interrupt each other. Post order: task1->task2. Exec order: task1->task2. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndInterrupt001, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndInterrupt001 START"); + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::TASK_CRITICAL_CHANGE_BEGIN, true)); + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::TASK_CRITICAL_CHANGE_BEGIN, false)); + + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::TASK_SWITCH_IME_BEGIN, true)); + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::TASK_SWITCH_IME_BEGIN, false)); + + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::ON_FOCUSED, true)); + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::ON_FOCUSED, false)); + + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestSameInterrupt(SaTaskCode::START_INPUT, false)); +} + +/** + * @tc.name: TestPauseAndInterrupt002 + * @tc.desc: Post order: higher[paused]->lower->resume. Exec order: higher[paused]->resume->higher[resumed]->lowerTask + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndInterrupt002, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndInterrupt002 START"); + // critical task paused, can not be interrupted by lower task. + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::SWITCH_INPUT_METHOD, true)); + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::SWITCH_INPUT_METHOD, false)); + + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::ON_FOCUSED, true)); + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::ON_FOCUSED, false)); + + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::ON_WMS_SA_STARTED, SaTaskCode::START_INPUT, false)); + + // switch ime task paused, can not be interrupted by lower task. + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::ON_FOCUSED, true)); + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::ON_FOCUSED, false)); + + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestLowInterruptHigh(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::START_INPUT, false)); +} + +/** + * @tc.name: TestPauseAndInterrupt003 + * @tc.desc: Post order: lower[paused]->higher->resume, Execute order: lower[paused]->higher->end. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndInterrupt003, TestSize.Level0) +{ + // critical task can interrupt other paused task + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::SWITCH_INPUT_METHOD, true)); + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::SWITCH_INPUT_METHOD, false)); + + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::ON_FOCUSED, true)); + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::ON_FOCUSED, false)); + + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestHighInterruptLow(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::START_INPUT, false)); +} + +/** + * @tc.name: TestPauseAndPermitExecute001 + * @tc.desc: QUERY tasks can be executed when curTask_ is paused. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndPermitExecute001, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute001 START"); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::GET_CURRENT_INPUT_METHOD, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::GET_CURRENT_INPUT_METHOD, false)); + + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::GET_CURRENT_INPUT_METHOD, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::GET_CURRENT_INPUT_METHOD, false)); + + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::START_INPUT, SaTaskCode::GET_CURRENT_INPUT_METHOD, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::START_INPUT, SaTaskCode::GET_CURRENT_INPUT_METHOD, false)); +} + +/** + * @tc.name: TestPauseAndPermitExecute002 + * @tc.desc: RESUME tasks can be executed when curTask_ is paused. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndPermitExecute002, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute002 START"); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::SET_CORE_AND_AGENT, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::SET_CORE_AND_AGENT, false)); + + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::SET_CORE_AND_AGENT, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::SET_CORE_AND_AGENT, false)); + + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::START_INPUT, SaTaskCode::SET_CORE_AND_AGENT, true)); + EXPECT_TRUE(TestPauseAndExec(SaTaskCode::START_INPUT, SaTaskCode::SET_CORE_AND_AGENT, false)); +} + +/** + * @tc.name: TestPauseAndPermitExecute003 + * @tc.desc: REQUEST tasks from target app in WHITE_LIST can be executed when curTask_ is paused. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndPermitExecute003, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute003 START"); + EXPECT_TRUE( + TestPauseAndExecWhiteListRequest(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, true)); + EXPECT_TRUE( + TestPauseAndExecWhiteListRequest(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, false)); + + EXPECT_TRUE( + TestPauseAndExecWhiteListRequest(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, true)); + EXPECT_TRUE( + TestPauseAndExecWhiteListRequest(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, false)); + + EXPECT_TRUE(TestPauseAndExecWhiteListRequest(SaTaskCode::START_INPUT, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, true)); + EXPECT_TRUE(TestPauseAndExecWhiteListRequest(SaTaskCode::START_INPUT, SaTaskCode::UPDATE_LISTEN_EVENT_FLAG, false)); +} + +/** + * @tc.name: TestPauseAndPermitExecute004 + * @tc.desc: REQUEST tasks from target app not in WHITE_LIST will be dropped when curTask_ is paused. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(SaTaskManagerTest, TestPauseAndPermitExecute004, TestSize.Level0) +{ + IMSA_HILOGI("SaTaskManagerTest TestPauseAndPermitExecute004 START"); + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::ON_WMS_CONNECTED, SaTaskCode::START_INPUT, false)); + + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::START_INPUT, true)); + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::SWITCH_INPUT_METHOD, SaTaskCode::START_INPUT, false)); + + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::START_INPUT, SaTaskCode::SHOW_INPUT, true)); + EXPECT_TRUE(TestPauseAndExecNonWhiteListRequest(SaTaskCode::START_INPUT, SaTaskCode::SHOW_INPUT, false)); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file