From 8c360c8ffa1f77a7d412dd1ebb711a1e48213157 Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Wed, 23 Jul 2025 14:28:52 +0800 Subject: [PATCH] add response data Signed-off-by: zhaolinglan --- .../common/include/response_data_util.h | 71 ++++++ .../common/include/service_response_data.h | 173 ++++++++++++++ .../common/src/service_response_data.cpp | 226 ++++++++++++++++++ 3 files changed, 470 insertions(+) create mode 100644 frameworks/native/common/include/response_data_util.h create mode 100644 frameworks/native/common/include/service_response_data.h create mode 100644 frameworks/native/common/src/service_response_data.cpp 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 000000000..b23b19a41 --- /dev/null +++ b/frameworks/native/common/include/response_data_util.h @@ -0,0 +1,71 @@ +/* + * 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 { +inline constexpr size_t MAX_SIZE = 102400; +class ResponseDataUtil { +public: + template static bool Unmarshall(Parcel &in, std::vector &out) + { + int32_t len = 0; + if (!in.ReadInt32(len)) { + return false; + } + auto size = static_cast(len); + if (size < 0 || size > MAX_SIZE) { + return false; + } + out.clear(); + for (int32_t i = 0; i < size; ++i) { + T value; + if (!value.ReadFromParcel(in)) { + return false; + } + out.push_back(value); + } + return true; + } + + template static bool Marshall(const std::vector &in, Parcel &out) + { + auto size = in.size(); + if (size > INT32_MAX) { + return false; + } + if (!out.WriteInt32(static_cast(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 000000000..711b1ca92 --- /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 = 2, + TYPE_UINT32 = 3, + TYPE_INT64 = 4, + TYPE_UINT64 = 5, + TYPE_REMOTE_OBJECT = 6, + + // inner types + TYPE_PROPERTY = 7, + TYPE_PROPERTIES = 8, + TYPE_SUB_PROPERTY = 9, + TYPE_SUB_PROPERTIES = 10, + TYPE_START_INPUT_RESPONSE = 11, + TYPE_INPUT_START_INFO = 12, + + // external types + TYPE_AMS_ELEMENT_NAME = 13, + + 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 000000000..c79c5ff74 --- /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 = value; + } }, + { 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("invalid 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 -- Gitee