diff --git a/interfaces/inner_api/dataobs_manager/include/dataobs_mgr_changeinfo.h b/interfaces/inner_api/dataobs_manager/include/dataobs_mgr_changeinfo.h index 5175464ef3..70404e5a31 100644 --- a/interfaces/inner_api/dataobs_manager/include/dataobs_mgr_changeinfo.h +++ b/interfaces/inner_api/dataobs_manager/include/dataobs_mgr_changeinfo.h @@ -16,6 +16,7 @@ #define OHOS_ABILITY_RUNTIME_DATAOBS_MGR_CHANGENOTIFICATION_H #include +#include #include "uri.h" #include "message_parcel.h" @@ -29,14 +30,18 @@ struct ChangeInfo { OTHER, INVAILD, }; + using Value = std::variant>; + using VBucket = std::map; + using VBuckets = std::vector; - static bool Marshalling(const ChangeInfo &input, MessageParcel &data); - static bool Unmarshalling(ChangeInfo &output, MessageParcel &data); + static bool Marshalling(const ChangeInfo &input, MessageParcel &parcel); + static bool Unmarshalling(ChangeInfo &output, MessageParcel &parcel); ChangeType changeType_ = INVAILD; mutable std::list uris_ = {}; void *data_ = nullptr; uint32_t size_ = 0; + VBuckets valueBuckets_ = {}; static constexpr int LIST_MAX_COUNT = 3000; }; } // namespace AAFwk diff --git a/interfaces/inner_api/dataobs_manager/include/dataobs_utils.h b/interfaces/inner_api/dataobs_manager/include/dataobs_utils.h new file mode 100644 index 0000000000..103c1e221e --- /dev/null +++ b/interfaces/inner_api/dataobs_manager/include/dataobs_utils.h @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_DATAOBS_UTILS_H +#define OHOS_ABILITY_RUNTIME_DATAOBS_UTILS_H +#include +#include +#include +#include +#include +#include +#include + +#include "iremote_object.h" +#include "message_parcel.h" +namespace OHOS { +template +struct is_container : std::false_type { +}; +template +struct is_container> : std::true_type { +}; +template +struct is_container> : std::true_type { +}; +namespace DataObsUtils { +static inline bool Marshal(MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshal(MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(int64_t input, MessageParcel &data) +{ + return data.WriteInt64(input); +} + +static inline bool Unmarshalling(int64_t &output, MessageParcel &data) +{ + return data.ReadInt64(output); +} + +static inline bool Marshalling(double input, MessageParcel &data) +{ + return data.WriteDouble(input); +} + +static inline bool Unmarshalling(double &output, MessageParcel &data) +{ + return data.ReadDouble(output); +} + +static inline bool Marshalling(bool input, MessageParcel &data) +{ + return data.WriteBool(input); +} + +static inline bool Unmarshalling(bool &output, MessageParcel &data) +{ + return data.ReadBool(output); +} + +static inline bool Marshalling(const std::monostate &input, MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshalling(std::monostate &output, MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(const std::string &input, MessageParcel &data) +{ + return data.WriteString(input); +} + +static inline bool Unmarshalling(std::string &output, MessageParcel &data) +{ + return data.ReadString(output); +} + +static inline bool Marshalling(const std::vector &input, MessageParcel &data) +{ + return data.WriteUInt8Vector(input); +} + +static inline bool Unmarshalling(std::vector &output, MessageParcel &data) +{ + return data.ReadUInt8Vector(&output); +} + +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); + +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); + +template +bool Marshalling(const std::variant<_Types...> &input, MessageParcel &data); +template +bool Unmarshalling(std::variant<_Types...> &output, MessageParcel &data); + +template +bool Marshalling(const std::map &result, MessageParcel &parcel); +template +bool Unmarshalling(std::map &val, MessageParcel &parcel); + +template +bool Marshalling(const std::vector &val, MessageParcel &parcel); +template +bool Unmarshalling(std::vector &val, MessageParcel &parcel); + +template +bool Marshalling(const T &input, MessageParcel &data); +template +bool Unmarshalling(T &output, MessageParcel &data); + +template{}, int>::type = 0> +bool MarshalToContainer(const T &val, MessageParcel &parcel); +template{}, int>::type = 0> +bool UnmarshalFromContainer(T &val, MessageParcel &parcel); + +template +bool Marshal(MessageParcel &parcel, const T &first, const Types &...others); + +template +bool Unmarshal(MessageParcel &parcel, T &first, Types &...others); +} // namespace DataObsUtils + +template +bool DataObsUtils::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + return false; +} + +template +bool DataObsUtils::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + if (step == index) { + _First value{}; + auto success = DataObsUtils::Unmarshalling(value, data); + output = value; + return success; + } + return DataObsUtils::ReadVariant<_OutTp, _Rest...>(step + 1, index, output, data); +} + +template +bool DataObsUtils::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + return false; +} + +template +bool DataObsUtils::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + if (step == input.index()) { + return DataObsUtils::Marshalling(std::get<_First>(input), data); + } + return DataObsUtils::WriteVariant<_InTp, _Rest...>(step + 1, input, data); +} + +template +bool DataObsUtils::Marshalling(const std::variant<_Types...> &input, MessageParcel &data) +{ + uint32_t index = static_cast(input.index()); + if (!data.WriteUint32(index)) { + return false; + } + + return DataObsUtils::WriteVariant(0, input, data); +} + +template +bool DataObsUtils::Unmarshalling(std::variant<_Types...> &output, MessageParcel &data) +{ + uint32_t index = data.ReadUint32(); + if (index >= sizeof...(_Types)) { + return false; + } + + return DataObsUtils::ReadVariant(0, index, output, data); +} + +template +bool DataObsUtils::Marshalling(const std::map &result, MessageParcel &parcel) +{ + if (!parcel.WriteInt32(static_cast(result.size()))) { + return false; + } + for (const auto &entry : result) { + if (!DataObsUtils::Marshalling(entry.first, parcel)) { + return false; + } + if (!DataObsUtils::Marshalling(entry.second, parcel)) { + return false; + } + } + return true; +} + +template +bool DataObsUtils::Unmarshalling(std::map &val, MessageParcel &parcel) +{ + int32_t size = 0; + if (!parcel.ReadInt32(size)) { + return false; + } + if (size < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + if ((static_cast(size) > readAbleSize) || static_cast(size) > val.max_size()) { + return false; + } + + for (int32_t i = 0; i < size; i++) { + K key; + if (!DataObsUtils::Unmarshalling(key, parcel)) { + return false; + } + if (!DataObsUtils::Unmarshalling(val[key], parcel)) { + return false; + } + } + return true; +} + +template +bool DataObsUtils::Marshalling(const std::vector &val, MessageParcel &parcel) +{ + return DataObsUtils::MarshalToContainer(val, parcel); +} + +template +bool DataObsUtils::Unmarshalling(std::vector &val, MessageParcel &parcel) +{ + return DataObsUtils::UnmarshalFromContainer(val, parcel); +} + +template{}, int>::type> +bool DataObsUtils::MarshalToContainer(const T &val, MessageParcel &parcel) +{ + if (val.size() > INT_MAX) { + return false; + } + + if (!parcel.WriteInt32(static_cast(val.size()))) { + return false; + } + + for (auto &v : val) { + if (!DataObsUtils::Marshalling(v, parcel)) { + return false; + } + } + return true; +} + +template{}, int>::type> +bool DataObsUtils::UnmarshalFromContainer(T &val, MessageParcel &parcel) +{ + int32_t len = parcel.ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > val.max_size())) { + return false; + } + + val.clear(); + for (size_t i = 0; i < size; i++) { + typename T::value_type value; + if (!DataObsUtils::Unmarshalling(value, parcel)) { + return false; + } + val.emplace_back(std::move(value)); + } + return true; +} + +template +bool DataObsUtils::Marshal(MessageParcel &parcel, const T &first, const Types &...others) +{ + if (!DataObsUtils::Marshalling(first, parcel)) { + return false; + } + return DataObsUtils::Marshal(parcel, others...); +} + +template +bool DataObsUtils::Unmarshal(MessageParcel &parcel, T &first, Types &...others) +{ + if (!DataObsUtils::Unmarshalling(first, parcel)) { + return false; + } + return DataObsUtils::Unmarshal(parcel, others...); +} +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_DATAOBS_UTILS_H \ No newline at end of file diff --git a/services/dataobsmgr/src/dataobs_mgr_changeinfo.cpp b/services/dataobsmgr/src/dataobs_mgr_changeinfo.cpp index 1d5f969029..d2aaf6c094 100644 --- a/services/dataobsmgr/src/dataobs_mgr_changeinfo.cpp +++ b/services/dataobsmgr/src/dataobs_mgr_changeinfo.cpp @@ -14,32 +14,43 @@ */ #include #include "dataobs_mgr_changeinfo.h" +#include "dataobs_utils.h" #include "securec.h" namespace OHOS { namespace AAFwk { -bool ChangeInfo::Marshalling(const ChangeInfo &input, MessageParcel &data) +using Value = std::variant>; +using VBucket = std::map; +using VBuckets = std::vector; +bool ChangeInfo::Marshalling(const ChangeInfo &input, MessageParcel &parcel) { - if (!data.WriteUint32(static_cast(input.changeType_))) { + if (!parcel.WriteUint32(static_cast(input.changeType_))) { return false; } if (input.uris_.size() > std::numeric_limits::max() || - !data.WriteUint32(static_cast(input.uris_.size()))) { + !parcel.WriteUint32(static_cast(input.uris_.size()))) { return false; } for (auto const &uri : input.uris_) { - if (!data.WriteString(uri.ToString())) { + if (!parcel.WriteString(uri.ToString())) { return false; } } - if (!data.WriteUint32(input.size_)) { + if (!parcel.WriteUint32(input.size_)) { return false; } - return input.size_ == 0 || data.WriteBuffer(input.data_, input.size_); + if (!(input.size_ == 0 || parcel.WriteBuffer(input.data_, input.size_))) { + return false; + } + + if (!DataObsUtils::Marshal(parcel, input.valueBuckets_)) { + return false; + } + return true; } bool ChangeInfo::Unmarshalling(ChangeInfo &output, MessageParcel &parcel) @@ -75,10 +86,15 @@ bool ChangeInfo::Unmarshalling(ChangeInfo &output, MessageParcel &parcel) if (size > 0 && data == nullptr) { return false; } + VBuckets buckets; + if (!(DataObsUtils::Unmarshal(parcel, buckets))) { + return false; + } output.changeType_ = static_cast(changeType); std::swap(output.uris_, uris); output.data_ = const_cast(data); output.size_ = size; + output.valueBuckets_ = std::move(buckets); return true; } } // namespace AAFwk diff --git a/services/dataobsmgr/src/dataobs_mgr_inner_ext.cpp b/services/dataobsmgr/src/dataobs_mgr_inner_ext.cpp index 00fdd00183..c9ee6f9191 100644 --- a/services/dataobsmgr/src/dataobs_mgr_inner_ext.cpp +++ b/services/dataobsmgr/src/dataobs_mgr_inner_ext.cpp @@ -104,7 +104,8 @@ Status DataObsMgrInnerExt::HandleNotifyChange(const ChangeInfo &changeInfo) } for (const auto &[obs, value] : changeRes) { if (obs != nullptr && !value.empty()) { - obs->OnChangeExt({ changeInfo.changeType_, move(value), changeInfo.data_, changeInfo.size_ }); + obs->OnChangeExt( + { changeInfo.changeType_, move(value), changeInfo.data_, changeInfo.size_, changeInfo.valueBuckets_ }); } }