已开启
test #872
xhz-sz创建于 9 天前
test #872
已开启
共 12 个文件变更+902-102
| @@ -154,7 +154,9 @@ ohos_shared_library("zuri") { | |||
| 154 | config("want_config") { | 154 | config("want_config") { |
| 155 | visibility = [ ":*" ] | 155 | visibility = [ ":*" ] |
| 156 | visibility += [ "./test/fuzztest/*" ] | 156 | visibility += [ "./test/fuzztest/*" ] |
| 157 | - include_dirs = [] | 157 | + include_dirs = [ |
| 158 | + "interfaces/kits/native/want/src", | ||
| 159 | + ] | ||
| 158 | cflags = [] | 160 | cflags = [] |
| 159 | if (target_cpu == "arm") { | 161 | if (target_cpu == "arm") { |
| 160 | cflags += [ "-DBINDER_IPC_32BIT" ] | 162 | cflags += [ "-DBINDER_IPC_32BIT" ] |
| @@ -178,6 +180,11 @@ config("want_public_config") { | |||
| 178 | ] | 180 | ] |
| 179 | } | 181 | } |
| 180 | 182 | ||
| 183 | +config("want_fd_adapter_config") { | ||
| 184 | + visibility = [ ":*" ] | ||
| 185 | + include_dirs = [ "interfaces/inner_api/want/include" ] | ||
| 186 | +} | ||
| 187 | + | ||
| 181 | config("want_all_dependent_config") { | 188 | config("want_all_dependent_config") { |
| 182 | include_dirs = [ "${ability_base_kits_native_path}/want/include" ] | 189 | include_dirs = [ "${ability_base_kits_native_path}/want/include" ] |
| 183 | } | 190 | } |
| @@ -197,9 +204,11 @@ ohos_shared_library("want") { | |||
| 197 | "interfaces/kits/native/want/src/patterns_matcher.cpp", | 204 | "interfaces/kits/native/want/src/patterns_matcher.cpp", |
| 198 | "interfaces/kits/native/want/src/skills.cpp", | 205 | "interfaces/kits/native/want/src/skills.cpp", |
| 199 | "interfaces/kits/native/want/src/want.cpp", | 206 | "interfaces/kits/native/want/src/want.cpp", |
| 207 | + "interfaces/kits/native/want/src/want_fd_value.cpp", | ||
| 200 | "interfaces/kits/native/want/src/want_params.cpp", | 208 | "interfaces/kits/native/want/src/want_params.cpp", |
| 201 | "interfaces/kits/native/want/src/want_params_wrapper.cpp", | 209 | "interfaces/kits/native/want/src/want_params_wrapper.cpp", |
| 202 | "interfaces/kits/native/want/src/want_params_wrapper_json.cpp", | 210 | "interfaces/kits/native/want/src/want_params_wrapper_json.cpp", |
| 211 | + "interfaces/inner_api/want/src/want_fd_adapter.cpp", | ||
| 203 | ] | 212 | ] |
| 204 | 213 | ||
| 205 | deps = [ | 214 | deps = [ |
| @@ -226,6 +235,7 @@ ohos_shared_library("want") { | |||
| 226 | configs = [ | 235 | configs = [ |
| 227 | ":want_config", | 236 | ":want_config", |
| 228 | ":want_exceptions_config", | 237 | ":want_exceptions_config", |
| 238 | + ":want_fd_adapter_config", | ||
| 229 | ] | 239 | ] |
| 230 | public_configs += [ ":want_public_config" ] | 240 | public_configs += [ ":want_public_config" ] |
| 231 | subsystem_name = "ability" | 241 | subsystem_name = "ability" |
| @@ -442,6 +452,7 @@ ohos_shared_library("ability_base_want") { | |||
| 442 | branch_protector_ret = "pac_ret" | 452 | branch_protector_ret = "pac_ret" |
| 443 | 453 | ||
| 444 | public_configs = [ ":ability_base_ndk_config" ] | 454 | public_configs = [ ":ability_base_ndk_config" ] |
| 455 | + configs = [ ":want_fd_adapter_config" ] | ||
| 445 | 456 | ||
| 446 | sources = [ | 457 | sources = [ |
| 447 | "interfaces/kits/c/cwant/src/want.cpp", | 458 | "interfaces/kits/c/cwant/src/want.cpp", |
| @@ -31,8 +31,16 @@ ErrCode Integer::GetValue(int &value) /* [out] */ | |||
| 31 | 31 | ||
| 32 | bool Integer::Equals(IObject &other) /* [in] */ | 32 | bool Integer::Equals(IObject &other) /* [in] */ |
| 33 | { | 33 | { |
| 34 | - Integer *otherObj = static_cast<Integer *>(IInteger::Query(&other)); | 34 | + IInteger *otherObj = IInteger::Query(&other); |
| 35 | - return otherObj != nullptr && otherObj->value_ == value_; | 35 | + if (otherObj == nullptr) { |
| 36 | + return false; | ||
| 37 | + } | ||
| 38 | + int otherValue = 0; | ||
| 39 | + ErrCode ret = otherObj->GetValue(otherValue); | ||
| 40 | + if (ret != ERR_OK) { | ||
| 41 | + return false; | ||
| 42 | + } | ||
| 43 | + return otherValue == value_; | ||
| 36 | } | 44 | } |
| 37 | 45 | ||
| 38 | std::string Integer::ToString() | 46 | std::string Integer::ToString() |
| @@ -0,0 +1,43 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace AAFwk { | ||
| 24 | + | ||
| 25 | +class WantFdAdapter final { | ||
| 26 | +public: | ||
| 27 | + static bool TryExtractFd(const sptr<IInterface> &value, int &outFd); | ||
| 28 | + | ||
| 29 | + // 成功:params 接管 fd(OWNED),并在 params 中建立 FD marker。 | ||
| 30 | + // 失败:若 fd 有效则由本函数关闭 fd,params 保持原状态。返回 false。 | ||
| 31 | + static bool SetOwnedFd(WantParams ¶ms, const std::string &key, int fd); | ||
| 32 | + // 成功:params 保存借用视图(BORROWED),不持有 close 责任。 | ||
| 33 | + // 失败:不关闭 fd(外部 owner 保留),params 保持原状态。返回 false。 | ||
| 34 | + static bool SetBorrowedFd(WantParams ¶ms, const std::string &key, int fd); | ||
| 35 | + | ||
| 36 | +private: | ||
| 37 | + WantFdAdapter() = delete; | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +} // namespace AAFwk | ||
| 41 | +} // namespace OHOS | ||
| 42 | + | ||
| 43 | + | ||
| @@ -0,0 +1,132 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace AAFwk { | ||
| 28 | + | ||
| 29 | +bool WantFdAdapter::TryExtractFd(const sptr<IInterface> &value, int &outFd) | ||
| 30 | +{ | ||
| 31 | + if (value == nullptr) { | ||
| 32 | + return false; | ||
| 33 | + } | ||
| 34 | + IWantParams *wrapper = IWantParams::Query(value); | ||
| 35 | + if (wrapper == nullptr) { | ||
| 36 | + return false; | ||
| 37 | + } | ||
| 38 | + WantParams inner = WantParamWrapper::Unbox(wrapper); | ||
| 39 | + const auto &innerParams = inner.GetParams(); | ||
| 40 | + | ||
| 41 | + auto typeIt = innerParams.find(TYPE_PROPERTY); | ||
| 42 | + if (typeIt == innerParams.end()) { | ||
| 43 | + return false; | ||
| 44 | + } | ||
| 45 | + IString *strValue = IString::Query(typeIt->second); | ||
| 46 | + if (strValue == nullptr) { | ||
| 47 | + return false; | ||
| 48 | + } | ||
| 49 | + if (String::Unbox(strValue) != FD) { | ||
| 50 | + return false; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + auto valueIt = innerParams.find(VALUE_PROPERTY); | ||
| 54 | + if (valueIt == innerParams.end()) { | ||
| 55 | + return false; | ||
| 56 | + } | ||
| 57 | + IInteger *intValue = IInteger::Query(valueIt->second); | ||
| 58 | + if (intValue == nullptr) { | ||
| 59 | + return false; | ||
| 60 | + } | ||
| 61 | + int fd = 0; | ||
| 62 | + if (intValue->GetValue(fd) != ERR_OK) { | ||
| 63 | + return false; | ||
| 64 | + } | ||
| 65 | + if (fd < 0) { | ||
| 66 | + return false; | ||
| 67 | + } | ||
| 68 | + outFd = fd; | ||
| 69 | + return true; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +bool WantFdAdapter::SetOwnedFd(WantParams ¶ms, const std::string &key, int fd) | ||
| 73 | +{ | ||
| 74 | + if (fd < 0) { | ||
| 75 | + ABILITYBASE_LOGE("invalid fd: %{public}d", fd); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + sptr<IInteger> value = WantFdValue::Adopt(fd); | ||
| 79 | + if (value == nullptr) { | ||
| 80 | + ABILITYBASE_LOGE("adopt fd failed, key: %{public}s, fd: %{public}d", key.c_str(), fd); | ||
| 81 | + close(fd); | ||
| 82 | + return false; | ||
| 83 | + } | ||
| 84 | + sptr<IString> type = String::Box(FD); | ||
| 85 | + if (type == nullptr) { | ||
| 86 | + ABILITYBASE_LOGE("box type failed, key: %{public}s", key.c_str()); | ||
| 87 | + return false; | ||
| 88 | + } | ||
| 89 | + WantParams wp; | ||
| 90 | + wp.SetParam(TYPE_PROPERTY, type); | ||
| 91 | + wp.SetParam(VALUE_PROPERTY, value); | ||
| 92 | + sptr<IWantParams> pWantParams = WantParamWrapper::Box(wp); | ||
| 93 | + if (pWantParams == nullptr) { | ||
| 94 | + ABILITYBASE_LOGE("box fd param failed, key: %{public}s", key.c_str()); | ||
| 95 | + return false; | ||
| 96 | + } | ||
| 97 | + params.SetParam(key, pWantParams); | ||
| 98 | + params.RebuildFdsMirror(); | ||
| 99 | + return true; | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +bool WantFdAdapter::SetBorrowedFd(WantParams ¶ms, const std::string &key, int fd) | ||
| 103 | +{ | ||
| 104 | + if (fd < 0) { | ||
| 105 | + ABILITYBASE_LOGE("invalid fd: %{public}d", fd); | ||
| 106 | + return false; | ||
| 107 | + } | ||
| 108 | + sptr<IInteger> value = WantFdValue::Borrow(fd); | ||
| 109 | + if (value == nullptr) { | ||
| 110 | + ABILITYBASE_LOGE("borrow fd failed, key: %{public}s, fd: %{public}d", key.c_str(), fd); | ||
| 111 | + return false; | ||
| 112 | + } | ||
| 113 | + sptr<IString> type = String::Box(FD); | ||
| 114 | + if (type == nullptr) { | ||
| 115 | + ABILITYBASE_LOGE("box type failed, key: %{public}s", key.c_str()); | ||
| 116 | + return false; | ||
| 117 | + } | ||
| 118 | + WantParams wp; | ||
| 119 | + wp.SetParam(TYPE_PROPERTY, type); | ||
| 120 | + wp.SetParam(VALUE_PROPERTY, value); | ||
| 121 | + sptr<IWantParams> pWantParams = WantParamWrapper::Box(wp); | ||
| 122 | + if (pWantParams == nullptr) { | ||
| 123 | + ABILITYBASE_LOGE("box fd param failed, key: %{public}s", key.c_str()); | ||
| 124 | + return false; | ||
| 125 | + } | ||
| 126 | + params.SetParam(key, pWantParams); | ||
| 127 | + params.RebuildFdsMirror(); | ||
| 128 | + return true; | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +} // namespace AAFwk | ||
| 132 | +} // namespace OHOS | ||
| @@ -15,13 +15,17 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 20 | 23 | ||
| 21 | 24 | ||
| 22 | 25 | ||
| 23 | 26 | ||
| 24 | 27 | ||
| 28 | + | ||
| 25 | 29 | ||
| 26 | 30 | ||
| 27 | namespace OHOS { | 31 | namespace OHOS { |
| @@ -55,72 +59,47 @@ namespace AAFwk { | |||
| 55 | wantParams.SetParam(it.first, Double::Box(it.second)); | 59 | wantParams.SetParam(it.first, Double::Box(it.second)); |
| 56 | } | 60 | } |
| 57 | 61 | ||
| 58 | - for (auto it : cwant.fds) { | 62 | + std::vector<std::pair<std::string, int32_t>> stagedFds; |
| 63 | + stagedFds.reserve(cwant.fds.size()); | ||
| 64 | + for (const auto &it : cwant.fds) { | ||
| 59 | ABILITYBASE_LOGD("fd key: %{public}s, value: %{public}d", it.first.c_str(), it.second); | 65 | ABILITYBASE_LOGD("fd key: %{public}s, value: %{public}d", it.first.c_str(), it.second); |
| 60 | - WantParams wp; | ||
| 61 | - wp.SetParam(TYPE_PROPERTY, String::Box(FD)); | ||
| 62 | int32_t new_fd = isDup ? dup(it.second) : it.second; | 66 | int32_t new_fd = isDup ? dup(it.second) : it.second; |
| 63 | - wp.SetParam(VALUE_PROPERTY, Integer::Box(new_fd)); | 67 | + if (isDup && new_fd < 0) { |
| 64 | - OHOS::sptr<IWantParams> pWantParams = WantParamWrapper::Box(wp); | 68 | + ABILITYBASE_LOGE("dup failed for key: %{public}s, errno: %{public}d", it.first.c_str(), errno); |
| 65 | - if (pWantParams != nullptr) { | 69 | + for (const auto &staged : stagedFds) { |
| 66 | - wantParams.SetParam(it.first, pWantParams); | 70 | + close(staged.second); |
| 71 | + } | ||
| 72 | + return ABILITY_BASE_ERROR_CODE_PARAM_INVALID; | ||
| 73 | + } | ||
| 74 | + stagedFds.emplace_back(it.first, new_fd); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + for (size_t i = 0; i < stagedFds.size(); ++i) { | ||
| 78 | + const auto &staged = stagedFds[i]; | ||
| 79 | + bool ok = isDup ? WantFdAdapter::SetOwnedFd(wantParams, staged.first, staged.second) | ||
| 80 | + : WantFdAdapter::SetBorrowedFd(wantParams, staged.first, staged.second); | ||
| 81 | + if (!ok) { | ||
| 82 | + ABILITYBASE_LOGE("set fd failed, key: %{public}s", staged.first.c_str()); | ||
| 83 | + for (size_t j = i + 1; j < stagedFds.size(); ++j) { | ||
| 84 | + if (isDup) { | ||
| 85 | + close(stagedFds[j].second); | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + return ABILITY_BASE_ERROR_CODE_PARAM_INVALID; | ||
| 67 | } | 89 | } |
| 68 | } | 90 | } |
| 69 | want.SetParams(wantParams); | 91 | want.SetParams(wantParams); |
| 70 | return ABILITY_BASE_ERROR_CODE_NO_ERROR; | 92 | return ABILITY_BASE_ERROR_CODE_NO_ERROR; |
| 71 | } | 93 | } |
| 72 | 94 | ||
| 73 | -constexpr int32_t FD_NULL = -1; | ||
| 74 | -constexpr int32_t FD_SIZE = 2; | ||
| 75 | - | ||
| 76 | -std::pair<std::string, int> GetFD(std::pair<std::string, sptr<IInterface>> fdparams) | ||
| 77 | -{ | ||
| 78 | - std::pair<std::string, int> fd = {"", FD_NULL}; | ||
| 79 | - ABILITYBASE_LOGD("params key: %{public}s", fdparams.first.c_str()); | ||
| 80 | - auto wantParams = WantParamWrapper::Unbox(IWantParams::Query(fdparams.second)); | ||
| 81 | - auto params = wantParams.GetParams(); | ||
| 82 | - if (params.size() != FD_SIZE) { | ||
| 83 | - ABILITYBASE_LOGD("params key: %{public}s not fd", fdparams.first.c_str()); | ||
| 84 | - return fd; | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - auto typeIt = params.find(TYPE_PROPERTY); | ||
| 88 | - if (typeIt == params.end()) { | ||
| 89 | - ABILITYBASE_LOGD("params key: %{public}s not find FD_TYPE", fdparams.first.c_str()); | ||
| 90 | - return fd; | ||
| 91 | - } | ||
| 92 | - IString *strValue = IString::Query(typeIt->second); | ||
| 93 | - if (strValue == nullptr) { | ||
| 94 | - ABILITYBASE_LOGD("params key: %{public}s FD_TYPE not string", fdparams.first.c_str()); | ||
| 95 | - return fd; | ||
| 96 | - } | ||
| 97 | - std::string typeString = String::Unbox(strValue); | ||
| 98 | - if (typeString != FD) { | ||
| 99 | - ABILITYBASE_LOGD("params key: %{public}s not FD", fdparams.first.c_str()); | ||
| 100 | - return fd; | ||
| 101 | - } | ||
| 102 | - | ||
| 103 | - auto valueIt = params.find(VALUE_PROPERTY); | ||
| 104 | - if (valueIt == params.end()) { | ||
| 105 | - ABILITYBASE_LOGD("params key: %{public}s not find FD_VALUE", fdparams.first.c_str()); | ||
| 106 | - return fd; | ||
| 107 | - } | ||
| 108 | - IInteger *intValue = IInteger::Query(valueIt->second); | ||
| 109 | - if (intValue == nullptr) { | ||
| 110 | - ABILITYBASE_LOGD("params key: %{public}s FD_VALUE not int", fdparams.first.c_str()); | ||
| 111 | - return fd; | ||
| 112 | - } | ||
| 113 | - ABILITYBASE_LOGD("params key: %{public}s, value: %{public}d", fdparams.first.c_str(), Integer::Unbox(intValue)); | ||
| 114 | - fd = {fdparams.first, Integer::Unbox(intValue)}; | ||
| 115 | - return fd; | ||
| 116 | -} | ||
| 117 | - | ||
| 118 | [[maybe_unused]] AbilityBase_ErrorCode CWantManager::TransformToCWantWithoutElement( | 95 | [[maybe_unused]] AbilityBase_ErrorCode CWantManager::TransformToCWantWithoutElement( |
| 119 | Want want, bool isDup, AbilityBase_Want &cwant) | 96 | Want want, bool isDup, AbilityBase_Want &cwant) |
| 120 | { | 97 | { |
| 121 | cwant.uri = want.GetUriString(); | 98 | cwant.uri = want.GetUriString(); |
| 122 | WantParams wantParams = want.GetParams(); | 99 | WantParams wantParams = want.GetParams(); |
| 123 | auto params = wantParams.GetParams(); | 100 | auto params = wantParams.GetParams(); |
| 101 | + | ||
| 102 | + std::vector<std::pair<std::string, int32_t>> stagedFds; | ||
| 124 | for (const auto& iter : params) { | 103 | for (const auto& iter : params) { |
| 125 | if (IString::Query(iter.second) != nullptr) { | 104 | if (IString::Query(iter.second) != nullptr) { |
| 126 | ABILITYBASE_LOGD("params key: %{public}s, value: %{public}s", | 105 | ABILITYBASE_LOGD("params key: %{public}s, value: %{public}s", |
| @@ -147,15 +126,32 @@ std::pair<std::string, int> GetFD(std::pair<std::string, sptr<IInterface>> fdpar | |||
| 147 | cwant.doubleParams.insert( | 126 | cwant.doubleParams.insert( |
| 148 | std::pair<std::string, double>(iter.first, Double::Unbox(IDouble::Query(iter.second)))); | 127 | std::pair<std::string, double>(iter.first, Double::Unbox(IDouble::Query(iter.second)))); |
| 149 | } else if (IWantParams::Query(iter.second) != nullptr) { | 128 | } else if (IWantParams::Query(iter.second) != nullptr) { |
| 150 | - auto fd = GetFD(iter); | 129 | + int extractedFd = -1; |
| 151 | - if (fd.first != iter.first || fd.second == FD_NULL) { | 130 | + if (!WantFdAdapter::TryExtractFd(iter.second, extractedFd)) { |
| 152 | continue; | 131 | continue; |
| 153 | } | 132 | } |
| 154 | - cwant.fds.insert(fd); | 133 | + if (isDup) { |
| 134 | + int32_t dupFd = dup(extractedFd); | ||
| 135 | + if (dupFd < 0) { | ||
| 136 | + ABILITYBASE_LOGE("dup failed for key: %{public}s, errno: %{public}d", | ||
| 137 | + iter.first.c_str(), errno); | ||
| 138 | + for (const auto &staged : stagedFds) { | ||
| 139 | + close(staged.second); | ||
| 140 | + } | ||
| 141 | + return ABILITY_BASE_ERROR_CODE_PARAM_INVALID; | ||
| 142 | + } | ||
| 143 | + stagedFds.emplace_back(iter.first, dupFd); | ||
| 144 | + } else { | ||
| 145 | + stagedFds.emplace_back(iter.first, extractedFd); | ||
| 146 | + } | ||
| 155 | } | 147 | } |
| 156 | } | 148 | } |
| 157 | 149 | ||
| 150 | + for (const auto &staged : stagedFds) { | ||
| 151 | + cwant.fds.insert(staged); | ||
| 152 | + } | ||
| 153 | + | ||
| 158 | return ABILITY_BASE_ERROR_CODE_NO_ERROR; | 154 | return ABILITY_BASE_ERROR_CODE_NO_ERROR; |
| 159 | } | 155 | } |
| 160 | } // namespace AAFwk | 156 | } // namespace AAFwk |
| 161 | -} // namespace OHOS | 157 | +} // namespace OHOS |
| @@ -217,10 +217,11 @@ private: | |||
| 217 | bool ReadUnsupportedData(Parcel &parcel, const std::string &key, int type); | 217 | bool ReadUnsupportedData(Parcel &parcel, const std::string &key, int type); |
| 218 | 218 | ||
| 219 | friend class WantParamWrapper; | 219 | friend class WantParamWrapper; |
| 220 | + friend class WantFdAdapter; | ||
| 220 | // inner use function | 221 | // inner use function |
| 221 | bool NewArrayData(IArray *source, sptr<IArray> &dest); | 222 | bool NewArrayData(IArray *source, sptr<IArray> &dest); |
| 222 | bool NewParams(const WantParams &source, WantParams &dest); | 223 | bool NewParams(const WantParams &source, WantParams &dest); |
| 223 | - bool NewFds(const WantParams &source, WantParams &dest); | 224 | + void RebuildFdsMirror(); |
| 224 | bool AddWantParamToInterfaceVector(const sptr<WantParams> &value, | 225 | bool AddWantParamToInterfaceVector(const sptr<WantParams> &value, |
| 225 | std::vector<sptr<IInterface>> &array) const; | 226 | std::vector<sptr<IInterface>> &array) const; |
| 226 | 227 | ||
| @@ -0,0 +1,126 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace AAFwk { | ||
| 25 | + | ||
| 26 | +const InterfaceID g_IID_IWantFdValue = { | ||
| 27 | + 0xb3c4d5e6, 0xf7a8, 0x4b9c, 0x0d1e, {0x2, 0xf, 0x3, 0xa, 0x4, 0xb, 0x5, 0xc, 0x6, 0xd, 0x7, 0xe} | ||
| 28 | +}; | ||
| 29 | + | ||
| 30 | +WantFdValue::WantFdValue(int fd, Ownership ownership) | ||
| 31 | + : fd_(fd), ownership_(ownership) {} | ||
| 32 | + | ||
| 33 | +WantFdValue::~WantFdValue() | ||
| 34 | +{ | ||
| 35 | + if (ownership_ == Ownership::OWNED && fd_ >= 0) { | ||
| 36 | + ABILITYBASE_LOGI("close fd: %{public}d", fd_); | ||
| 37 | + close(fd_); | ||
| 38 | + } | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +sptr<WantFdValue> WantFdValue::Adopt(int fd) | ||
| 42 | +{ | ||
| 43 | + if (fd < 0) { | ||
| 44 | + return nullptr; | ||
| 45 | + } | ||
| 46 | + return sptr<WantFdValue>(new (std::nothrow) WantFdValue(fd, Ownership::OWNED)); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +sptr<WantFdValue> WantFdValue::Borrow(int fd) | ||
| 50 | +{ | ||
| 51 | + if (fd < 0) { | ||
| 52 | + return nullptr; | ||
| 53 | + } | ||
| 54 | + return sptr<WantFdValue>(new (std::nothrow) WantFdValue(fd, Ownership::BORROWED)); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +void WantFdValue::IncStrongRef(const void *id) | ||
| 58 | +{ | ||
| 59 | + Object::IncStrongRef(id); | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +void WantFdValue::DecStrongRef(const void *id) | ||
| 63 | +{ | ||
| 64 | + Object::DecStrongRef(id); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +IInterface *WantFdValue::Query(const InterfaceID &iid) | ||
| 68 | +{ | ||
| 69 | + if (iid == g_IID_IInteger) { | ||
| 70 | + return static_cast<IInteger *>(this); | ||
| 71 | + } | ||
| 72 | + if (iid == g_IID_IWantFdValue) { | ||
| 73 | + return static_cast<IWantFdValue *>(this); | ||
| 74 | + } | ||
| 75 | + if (iid == g_IID_IInterface) { | ||
| 76 | + return static_cast<IInteger *>(this); | ||
| 77 | + } | ||
| 78 | + return Object::Query(iid); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +InterfaceID WantFdValue::GetInterfaceID(IInterface *object) | ||
| 82 | +{ | ||
| 83 | + if (object == static_cast<IInteger *>(this)) { | ||
| 84 | + return g_IID_IInteger; | ||
| 85 | + } | ||
| 86 | + if (object == static_cast<IWantFdValue *>(this)) { | ||
| 87 | + return g_IID_IWantFdValue; | ||
| 88 | + } | ||
| 89 | + return Object::GetInterfaceID(object); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +ErrCode WantFdValue::GetValue(int &value) | ||
| 93 | +{ | ||
| 94 | + VALIDATE_NOT_NULL(&value); | ||
| 95 | + value = fd_; | ||
| 96 | + return ERR_OK; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +bool WantFdValue::Equals(IObject &other) | ||
| 100 | +{ | ||
| 101 | + IInteger *otherInt = IInteger::Query(&other); | ||
| 102 | + if (otherInt == nullptr) { | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + int otherValue = 0; | ||
| 106 | + otherInt->GetValue(otherValue); | ||
| 107 | + return otherValue == fd_; | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +std::string WantFdValue::ToString() | ||
| 111 | +{ | ||
| 112 | + return std::to_string(fd_); | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +int WantFdValue::GetFd() const | ||
| 116 | +{ | ||
| 117 | + return fd_; | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +bool WantFdValue::IsOwned() const | ||
| 121 | +{ | ||
| 122 | + return ownership_ == Ownership::OWNED; | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +} // namespace AAFwk | ||
| 126 | +} // namespace OHOS | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace OHOS { | ||
| 23 | +namespace AAFwk { | ||
| 24 | + | ||
| 25 | +enum class Ownership { | ||
| 26 | + OWNED, | ||
| 27 | + BORROWED, | ||
| 28 | +}; | ||
| 29 | + | ||
| 30 | +INTERFACE(IWantFdValue, b3c4d5e6 - f7a8 - 4b9c - 0d1e - 2f3a4b5c6d7e) | ||
| 31 | +{ | ||
| 32 | + static IWantFdValue *Query(IInterface *value) | ||
| 33 | + { | ||
| 34 | + if (value == nullptr) { | ||
| 35 | + return nullptr; | ||
| 36 | + } | ||
| 37 | + return static_cast<IWantFdValue *>(value->Query(g_IID_IWantFdValue)); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + virtual int GetFd() const = 0; | ||
| 41 | + virtual bool IsOwned() const = 0; | ||
| 42 | +}; | ||
| 43 | + | ||
| 44 | +class WantFdValue final : public Object, public IInteger, private IWantFdValue { | ||
| 45 | +public: | ||
| 46 | + WantFdValue(int fd, Ownership ownership); | ||
| 47 | + ~WantFdValue(); | ||
| 48 | + | ||
| 49 | + static sptr<WantFdValue> Adopt(int fd); | ||
| 50 | + static sptr<WantFdValue> Borrow(int fd); | ||
| 51 | + | ||
| 52 | + void IncStrongRef(const void *id = nullptr) override; | ||
| 53 | + void DecStrongRef(const void *id = nullptr) override; | ||
| 54 | + IInterface *Query(const InterfaceID &iid) override; | ||
| 55 | + InterfaceID GetInterfaceID(IInterface *object) override; | ||
| 56 | + | ||
| 57 | + ErrCode GetValue(int &value) override; | ||
| 58 | + bool Equals(IObject &other) override; | ||
| 59 | + std::string ToString() override; | ||
| 60 | + | ||
| 61 | + int GetFd() const override; | ||
| 62 | + bool IsOwned() const override; | ||
| 63 | + | ||
| 64 | +private: | ||
| 65 | + const int fd_; | ||
| 66 | + const Ownership ownership_; | ||
| 67 | +}; | ||
| 68 | + | ||
| 69 | +} // namespace AAFwk | ||
| 70 | +} // namespace OHOS | ||
| 71 | + | ||
| 72 | + | ||
| @@ -32,6 +32,8 @@ | |||
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | + | ||
| 36 | + | ||
| 35 | 37 | ||
| 36 | 38 | ||
| 37 | 39 | ||
| @@ -325,7 +327,13 @@ std::string WantParams::GetStringByType(const sptr<IInterface> iIt, int typeId) | |||
| 325 | } else if (typeId == VALUE_TYPE_SHORT) { | 327 | } else if (typeId == VALUE_TYPE_SHORT) { |
| 326 | return static_cast<Short *>(IShort::Query(iIt))->ToString(); | 328 | return static_cast<Short *>(IShort::Query(iIt))->ToString(); |
| 327 | } else if (typeId == VALUE_TYPE_INT) { | 329 | } else if (typeId == VALUE_TYPE_INT) { |
| 328 | - return static_cast<Integer *>(IInteger::Query(iIt))->ToString(); | 330 | + IInteger *iInt = IInteger::Query(iIt); |
| 331 | + if (iInt == nullptr) { | ||
| 332 | + return ""; | ||
| 333 | + } | ||
| 334 | + int value = 0; | ||
| 335 | + iInt->GetValue(value); | ||
| 336 | + return std::to_string(value); | ||
| 329 | } else if (typeId == VALUE_TYPE_LONG) { | 337 | } else if (typeId == VALUE_TYPE_LONG) { |
| 330 | return static_cast<Long *>(ILong::Query(iIt))->ToString(); | 338 | return static_cast<Long *>(ILong::Query(iIt))->ToString(); |
| 331 | } else if (typeId == VALUE_TYPE_FLOAT) { | 339 | } else if (typeId == VALUE_TYPE_FLOAT) { |
| @@ -354,6 +362,7 @@ WantParams::WantParams(const WantParams &wantParams) | |||
| 354 | { | 362 | { |
| 355 | params_.clear(); | 363 | params_.clear(); |
| 356 | NewParams(wantParams, *this); | 364 | NewParams(wantParams, *this); |
| 365 | + RebuildFdsMirror(); | ||
| 357 | } | 366 | } |
| 358 | 367 | ||
| 359 | WantParams::WantParams(WantParams && other) noexcept | 368 | WantParams::WantParams(WantParams && other) noexcept |
| @@ -361,15 +370,16 @@ WantParams::WantParams(WantParams && other) noexcept | |||
| 361 | *this = std::move(other); | 370 | *this = std::move(other); |
| 362 | } | 371 | } |
| 363 | 372 | ||
| 364 | -// inner use function | 373 | +void WantParams::RebuildFdsMirror() |
| 365 | -bool WantParams::NewFds(const WantParams &source, WantParams &dest) | ||
| 366 | { | 374 | { |
| 367 | - // Deep copy | 375 | + fds_.clear(); |
| 368 | - for (auto it : source.fds_) { | 376 | + for (const auto &entry : params_) { |
| 369 | - dest.fds_[it.first] = it.second; | 377 | + int fd = -1; |
| 378 | + if (WantFdAdapter::TryExtractFd(entry.second, fd) && fd >= 0) { | ||
| 379 | + fds_[entry.first] = fd; | ||
| 380 | + } | ||
| 370 | } | 381 | } |
| 371 | - return true; | 382 | +} |
| 372 | -} // namespace AAFwk | ||
| 373 | 383 | ||
| 374 | // inner use function | 384 | // inner use function |
| 375 | bool WantParams::NewParams(const WantParams &source, WantParams &dest) | 385 | bool WantParams::NewParams(const WantParams &source, WantParams &dest) |
| @@ -387,6 +397,8 @@ bool WantParams::NewParams(const WantParams &source, WantParams &dest) | |||
| 387 | dest.params_[it->first] = Char::Box(Char::Unbox(IChar::Query(o))); | 397 | dest.params_[it->first] = Char::Box(Char::Unbox(IChar::Query(o))); |
| 388 | } else if (IShort::Query(o) != nullptr) { | 398 | } else if (IShort::Query(o) != nullptr) { |
| 389 | dest.params_[it->first] = Short::Box(Short::Unbox(IShort::Query(o))); | 399 | dest.params_[it->first] = Short::Box(Short::Unbox(IShort::Query(o))); |
| 400 | + } else if (IWantFdValue::Query(o) != nullptr) { | ||
| 401 | + dest.params_[it->first] = o; | ||
| 390 | } else if (IInteger::Query(o) != nullptr) { | 402 | } else if (IInteger::Query(o) != nullptr) { |
| 391 | dest.params_[it->first] = Integer::Box(Integer::Unbox(IInteger::Query(o))); | 403 | dest.params_[it->first] = Integer::Box(Integer::Unbox(IInteger::Query(o))); |
| 392 | } else if (ILong::Query(o) != nullptr) { | 404 | } else if (ILong::Query(o) != nullptr) { |
| @@ -451,9 +463,8 @@ WantParams &WantParams::operator=(const WantParams &other) | |||
| 451 | { | 463 | { |
| 452 | if (this != &other) { | 464 | if (this != &other) { |
| 453 | params_.clear(); | 465 | params_.clear(); |
| 454 | - fds_.clear(); | ||
| 455 | NewParams(other, *this); | 466 | NewParams(other, *this); |
| 456 | - NewFds(other, *this); | 467 | + RebuildFdsMirror(); |
| 457 | cachedUnsupportedData_.clear(); | 468 | cachedUnsupportedData_.clear(); |
| 458 | cachedUnsupportedData_ = other.cachedUnsupportedData_; | 469 | cachedUnsupportedData_ = other.cachedUnsupportedData_; |
| 459 | } | 470 | } |
| @@ -612,10 +623,20 @@ bool WantParams::CompareInterface(const sptr<IInterface> iIt1, const sptr<IInter | |||
| 612 | case VALUE_TYPE_SHORT: | 623 | case VALUE_TYPE_SHORT: |
| 613 | flag = static_cast<Short *>(IShort::Query(iIt1))->Equals(*(static_cast<Short *>(IShort::Query(iIt2)))); | 624 | flag = static_cast<Short *>(IShort::Query(iIt1))->Equals(*(static_cast<Short *>(IShort::Query(iIt2)))); |
| 614 | break; | 625 | break; |
| 615 | - case VALUE_TYPE_INT: | 626 | + case VALUE_TYPE_INT: { |
| 616 | - flag = | 627 | + IInteger *iInt1 = IInteger::Query(iIt1); |
| 617 | - static_cast<Integer *>(IInteger::Query(iIt1))->Equals(*(static_cast<Integer *>(IInteger::Query(iIt2)))); | 628 | + IInteger *iInt2 = IInteger::Query(iIt2); |
| 629 | + if (iInt1 == nullptr || iInt2 == nullptr) { | ||
| 630 | + flag = false; | ||
| 631 | + break; | ||
| 632 | + } | ||
| 633 | + int value1 = 0; | ||
| 634 | + int value2 = 0; | ||
| 635 | + iInt1->GetValue(value1); | ||
| 636 | + iInt2->GetValue(value2); | ||
| 637 | + flag = (value1 == value2); | ||
| 618 | break; | 638 | break; |
| 639 | + } | ||
| 619 | case VALUE_TYPE_LONG: | 640 | case VALUE_TYPE_LONG: |
| 620 | flag = static_cast<Long *>(ILong::Query(iIt1))->Equals(*(static_cast<Long *>(ILong::Query(iIt2)))); | 641 | flag = static_cast<Long *>(ILong::Query(iIt1))->Equals(*(static_cast<Long *>(ILong::Query(iIt2)))); |
| 621 | break; | 642 | break; |
| @@ -1624,14 +1645,12 @@ bool WantParams::ReadFromParcelFD(Parcel &parcel, const std::string &key) | |||
| 1624 | return false; | 1645 | return false; |
| 1625 | } | 1646 | } |
| 1626 | auto fd = messageParcel->ReadFileDescriptor(); | 1647 | auto fd = messageParcel->ReadFileDescriptor(); |
| 1648 | + if (fd < 0) { | ||
| 1649 | + ABILITYBASE_LOGE("invalid fd from parcel"); | ||
| 1650 | + return false; | ||
| 1651 | + } | ||
| 1627 | ABILITYBASE_LOGI("fd:%{public}d", fd); | 1652 | ABILITYBASE_LOGI("fd:%{public}d", fd); |
| 1628 | - WantParams wp; | 1653 | + return WantFdAdapter::SetOwnedFd(*this, key, fd); |
| 1629 | - wp.SetParam(TYPE_PROPERTY, String::Box(FD)); | ||
| 1630 | - wp.SetParam(VALUE_PROPERTY, Integer::Box(fd)); | ||
| 1631 | - sptr<AAFwk::IWantParams> pWantParams = AAFwk::WantParamWrapper::Box(wp); | ||
| 1632 | - SetParam(key, pWantParams); | ||
| 1633 | - fds_[key] = fd; | ||
| 1634 | - return true; | ||
| 1635 | } | 1654 | } |
| 1636 | 1655 | ||
| 1637 | bool WantParams::ReadFromParcelRemoteObject(Parcel &parcel, const std::string &key) | 1656 | bool WantParams::ReadFromParcelRemoteObject(Parcel &parcel, const std::string &key) |
| @@ -1867,40 +1886,58 @@ void WantParams::DumpInfo(int level) const | |||
| 1867 | 1886 | ||
| 1868 | void WantParams::CloseAllFd() | 1887 | void WantParams::CloseAllFd() |
| 1869 | { | 1888 | { |
| 1870 | - for (auto it : fds_) { | 1889 | + for (auto it = params_.begin(); it != params_.end();) { |
| 1871 | - if (it.second > 0) { | 1890 | + int fd = -1; |
| 1872 | - ABILITYBASE_LOGI("fd:%{public}d", it.second); | 1891 | + if (WantFdAdapter::TryExtractFd(it->second, fd)) { |
| 1873 | - close(it.second); | 1892 | + it = params_.erase(it); |
| 1893 | + } else { | ||
| 1894 | + ++it; | ||
| 1874 | } | 1895 | } |
| 1875 | - params_.erase(it.first); | ||
| 1876 | } | 1896 | } |
| 1877 | - fds_.clear(); | 1897 | + RebuildFdsMirror(); |
| 1878 | } | 1898 | } |
| 1879 | 1899 | ||
| 1880 | void WantParams::RemoveAllFd() | 1900 | void WantParams::RemoveAllFd() |
| 1881 | { | 1901 | { |
| 1882 | - for (auto it : fds_) { | 1902 | + CloseAllFd(); |
| 1883 | - params_.erase(it.first); | ||
| 1884 | - } | ||
| 1885 | - fds_.clear(); | ||
| 1886 | } | 1903 | } |
| 1887 | 1904 | ||
| 1888 | void WantParams::DupAllFd() | 1905 | void WantParams::DupAllFd() |
| 1889 | { | 1906 | { |
| 1890 | - for (auto it : fds_) { | 1907 | + std::vector<std::pair<std::string, int32_t>> stagedDups; |
| 1891 | - if (it.second > 0) { | 1908 | + std::vector<sptr<AAFwk::IWantParams>> stagedMarkers; |
| 1892 | - int dupFd = dup(it.second); | 1909 | + |
| 1893 | - if (dupFd > 0) { | 1910 | + for (const auto &[key, value] : params_) { |
| 1894 | - params_.erase(it.first); | 1911 | + int fd = -1; |
| 1895 | - WantParams wp; | 1912 | + if (!WantFdAdapter::TryExtractFd(value, fd) || fd < 0) { |
| 1896 | - wp.SetParam(TYPE_PROPERTY, String::Box(FD)); | 1913 | + continue; |
| 1897 | - wp.SetParam(VALUE_PROPERTY, Integer::Box(dupFd)); | ||
| 1898 | - sptr<AAFwk::IWantParams> pWantParams = AAFwk::WantParamWrapper::Box(wp); | ||
| 1899 | - SetParam(it.first, pWantParams); | ||
| 1900 | - fds_[it.first] = dupFd; | ||
| 1901 | - } | ||
| 1902 | } | 1914 | } |
| 1915 | + int32_t dupFd = dup(fd); | ||
| 1916 | + if (dupFd < 0) { | ||
| 1917 | + ABILITYBASE_LOGE("dup fd failed, key: %{public}s", key.c_str()); | ||
| 1918 | + stagedMarkers.clear(); | ||
| 1919 | + stagedDups.clear(); | ||
| 1920 | + return; | ||
| 1921 | + } | ||
| 1922 | + sptr<IInteger> newVal = WantFdValue::Adopt(dupFd); | ||
| 1923 | + WantParams wp; | ||
| 1924 | + wp.SetParam(TYPE_PROPERTY, String::Box(FD)); | ||
| 1925 | + wp.SetParam(VALUE_PROPERTY, newVal); | ||
| 1926 | + sptr<AAFwk::IWantParams> marker = AAFwk::WantParamWrapper::Box(wp); | ||
| 1927 | + if (marker == nullptr) { | ||
| 1928 | + ABILITYBASE_LOGE("box fd param failed, key: %{public}s", key.c_str()); | ||
| 1929 | + stagedMarkers.clear(); | ||
| 1930 | + stagedDups.clear(); | ||
| 1931 | + return; | ||
| 1932 | + } | ||
| 1933 | + stagedDups.emplace_back(key, dupFd); | ||
| 1934 | + stagedMarkers.emplace_back(marker); | ||
| 1903 | } | 1935 | } |
| 1936 | + | ||
| 1937 | + for (size_t i = 0; i < stagedDups.size(); ++i) { | ||
| 1938 | + params_[stagedDups[i].first] = stagedMarkers[i]; | ||
| 1939 | + } | ||
| 1940 | + RebuildFdsMirror(); | ||
| 1904 | } | 1941 | } |
| 1905 | 1942 | ||
| 1906 | void WantParams::GetCachedUnsupportedData(std::vector<UnsupportedData> &cachedUnsupportedData) const | 1943 | void WantParams::GetCachedUnsupportedData(std::vector<UnsupportedData> &cachedUnsupportedData) const |
| @@ -244,6 +244,33 @@ ohos_unittest("want_params_test") { | |||
| 244 | ] | 244 | ] |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | +ohos_unittest("want_fd_adapter_test") { | ||
| 248 | + module_out_path = want_output_path | ||
| 249 | + sources = [ "want/want_fd_adapter_test.cpp" ] | ||
| 250 | + | ||
| 251 | + configs = [ | ||
| 252 | + ":want_private_config", | ||
| 253 | + "${ability_base_path}:want_public_config", | ||
| 254 | + ] | ||
| 255 | + | ||
| 256 | + include_dirs = [ | ||
| 257 | + "${ability_base_path}/interfaces/kits/native/want/src", | ||
| 258 | + "${ability_base_path}/interfaces/inner_api/want/include", | ||
| 259 | + ] | ||
| 260 | + | ||
| 261 | + deps = [ | ||
| 262 | + "${ability_base_path}:base", | ||
| 263 | + "${ability_base_path}:want", | ||
| 264 | + ] | ||
| 265 | + | ||
| 266 | + external_deps = [ | ||
| 267 | + "c_utils:utils", | ||
| 268 | + "googletest:gtest_main", | ||
| 269 | + "hilog:libhilog", | ||
| 270 | + "ipc:ipc_core", | ||
| 271 | + ] | ||
| 272 | +} | ||
| 273 | + | ||
| 247 | ohos_unittest("want_params_wrapper_test") { | 274 | ohos_unittest("want_params_wrapper_test") { |
| 248 | module_out_path = want_output_path | 275 | module_out_path = want_output_path |
| 249 | sources = [ "want/want_params_wrapper_test.cpp" ] | 276 | sources = [ "want/want_params_wrapper_test.cpp" ] |
| @@ -831,6 +858,7 @@ group("unittest") { | |||
| 831 | ":user_object_wrapper_test", | 858 | ":user_object_wrapper_test", |
| 832 | ":view_data_test", | 859 | ":view_data_test", |
| 833 | ":want_params_test", | 860 | ":want_params_test", |
| 861 | + ":want_fd_adapter_test", | ||
| 834 | ":want_params_wrapper_test", | 862 | ":want_params_wrapper_test", |
| 835 | ":want_params_wrapper_json_test", | 863 | ":want_params_wrapper_json_test", |
| 836 | ":want_test", | 864 | ":want_test", |
| @@ -21,12 +21,27 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 24 | using namespace OHOS; | 27 | using namespace OHOS; |
| 25 | using namespace OHOS::AAFwk; | 28 | using namespace OHOS::AAFwk; |
| 26 | using testing::ext::TestSize; | 29 | using testing::ext::TestSize; |
| 27 | 30 | ||
| 28 | namespace OHOS { | 31 | namespace OHOS { |
| 29 | namespace AAFwk { | 32 | namespace AAFwk { |
| 33 | +class MockInteger final : public Object, public IInteger { | ||
| 34 | +public: | ||
| 35 | + explicit MockInteger(int value) : value_(value) {} | ||
| 36 | + IINTERFACE_DECL(); | ||
| 37 | + ErrCode GetValue(int &value) override { value = value_; return ERR_OK; } | ||
| 38 | + bool Equals(IObject &other) override { return false; } | ||
| 39 | + std::string ToString() override { return std::to_string(value_); } | ||
| 40 | +private: | ||
| 41 | + int value_; | ||
| 42 | +}; | ||
| 43 | +IINTERFACE_IMPL_1(MockInteger, Object, IInteger); | ||
| 44 | + | ||
| 30 | class AAfWKIntWrapperTest : public testing::Test { | 45 | class AAfWKIntWrapperTest : public testing::Test { |
| 31 | public: | 46 | public: |
| 32 | static void SetUpTestCase() {}; | 47 | static void SetUpTestCase() {}; |
| @@ -107,5 +122,40 @@ HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Parse_004, TestSize.Level1) | |||
| 107 | sptr<IInteger> result = Integer::Parse("abc123"); | 122 | sptr<IInteger> result = Integer::Parse("abc123"); |
| 108 | EXPECT_EQ(result, nullptr); | 123 | EXPECT_EQ(result, nullptr); |
| 109 | } | 124 | } |
| 125 | + | ||
| 126 | +HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Equals_SameValue, TestSize.Level1) | ||
| 127 | +{ | ||
| 128 | + Integer a(42); | ||
| 129 | + Integer b(42); | ||
| 130 | + EXPECT_TRUE(a.Equals(b)); | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Equals_DifferentValue, TestSize.Level1) | ||
| 134 | +{ | ||
| 135 | + Integer a(42); | ||
| 136 | + Integer b(99); | ||
| 137 | + EXPECT_FALSE(a.Equals(b)); | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Equals_MockIntegerSameValue, TestSize.Level1) | ||
| 141 | +{ | ||
| 142 | + Integer a(42); | ||
| 143 | + MockInteger b(42); | ||
| 144 | + EXPECT_TRUE(a.Equals(b)); | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Equals_MockIntegerDifferentValue, TestSize.Level1) | ||
| 148 | +{ | ||
| 149 | + Integer a(42); | ||
| 150 | + MockInteger b(99); | ||
| 151 | + EXPECT_FALSE(a.Equals(b)); | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +HWTEST_F(AAfWKIntWrapperTest, IntWrapperTest_Equals_NonIntegerObject, TestSize.Level1) | ||
| 155 | +{ | ||
| 156 | + Integer a(42); | ||
| 157 | + String str("hello"); | ||
| 158 | + EXPECT_FALSE(a.Equals(str)); | ||
| 159 | +} | ||
| 110 | } | 160 | } |
| 111 | } | 161 | } |
| @@ -0,0 +1,296 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +using namespace OHOS; | ||
| 31 | +using namespace OHOS::AAFwk; | ||
| 32 | +using testing::ext::TestSize; | ||
| 33 | + | ||
| 34 | +namespace OHOS { | ||
| 35 | +namespace AAFwk { | ||
| 36 | +namespace { | ||
| 37 | +sptr<IInterface> CreateFdMarker(int fd) | ||
| 38 | +{ | ||
| 39 | + WantParams wp; | ||
| 40 | + wp.SetParam(TYPE_PROPERTY, String::Box(FD)); | ||
| 41 | + wp.SetParam(VALUE_PROPERTY, Integer::Box(fd)); | ||
| 42 | + return WantParamWrapper::Box(wp); | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +int CreatePipeFd() | ||
| 46 | +{ | ||
| 47 | + int pipefd[2] = {-1, -1}; | ||
| 48 | + if (pipe(pipefd) != 0) { | ||
| 49 | + return -1; | ||
| 50 | + } | ||
| 51 | + close(pipefd[1]); | ||
| 52 | + return pipefd[0]; | ||
| 53 | +} | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +class WantFdAdapterTest : public testing::Test { | ||
| 57 | +public: | ||
| 58 | + static void SetUpTestCase() {}; | ||
| 59 | + static void TearDownTestCase() {}; | ||
| 60 | + void SetUp() {}; | ||
| 61 | + void TearDown() {}; | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +HWTEST_F(WantFdAdapterTest, TryExtractFd_ValidFdMarker, TestSize.Level1) | ||
| 65 | +{ | ||
| 66 | + int fd = CreatePipeFd(); | ||
| 67 | + ASSERT_GE(fd, 0); | ||
| 68 | + auto marker = CreateFdMarker(fd); | ||
| 69 | + int outFd = -1; | ||
| 70 | + EXPECT_TRUE(WantFdAdapter::TryExtractFd(marker, outFd)); | ||
| 71 | + EXPECT_EQ(fd, outFd); | ||
| 72 | + close(fd); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +HWTEST_F(WantFdAdapterTest, TryExtractFd_FdZero, TestSize.Level1) | ||
| 76 | +{ | ||
| 77 | + auto marker = CreateFdMarker(0); | ||
| 78 | + int outFd = -1; | ||
| 79 | + EXPECT_TRUE(WantFdAdapter::TryExtractFd(marker, outFd)); | ||
| 80 | + EXPECT_EQ(0, outFd); | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +HWTEST_F(WantFdAdapterTest, TryExtractFd_NegativeFd, TestSize.Level1) | ||
| 84 | +{ | ||
| 85 | + auto marker = CreateFdMarker(-1); | ||
| 86 | + int outFd = -1; | ||
| 87 | + EXPECT_FALSE(WantFdAdapter::TryExtractFd(marker, outFd)); | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +HWTEST_F(WantFdAdapterTest, TryExtractFd_PlainInteger, TestSize.Level1) | ||
| 91 | +{ | ||
| 92 | + auto value = Integer::Box(42); | ||
| 93 | + int outFd = -1; | ||
| 94 | + EXPECT_FALSE(WantFdAdapter::TryExtractFd(value, outFd)); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +HWTEST_F(WantFdAdapterTest, TryExtractFd_NullValue, TestSize.Level1) | ||
| 98 | +{ | ||
| 99 | + sptr<IInterface> nullValue = nullptr; | ||
| 100 | + int outFd = -1; | ||
| 101 | + EXPECT_FALSE(WantFdAdapter::TryExtractFd(nullValue, outFd)); | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +HWTEST_F(WantFdAdapterTest, Holder_OwnedClosesOnLastRef, TestSize.Level1) | ||
| 105 | +{ | ||
| 106 | + int fd = CreatePipeFd(); | ||
| 107 | + ASSERT_GE(fd, 0); | ||
| 108 | + { | ||
| 109 | + sptr<WantFdValue> value = WantFdValue::Adopt(fd); | ||
| 110 | + ASSERT_NE(value, nullptr); | ||
| 111 | + EXPECT_TRUE(value->IsOwned()); | ||
| 112 | + EXPECT_EQ(fd, value->GetFd()); | ||
| 113 | + } | ||
| 114 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +HWTEST_F(WantFdAdapterTest, Holder_BorrowedNeverCloses, TestSize.Level1) | ||
| 118 | +{ | ||
| 119 | + int fd = CreatePipeFd(); | ||
| 120 | + ASSERT_GE(fd, 0); | ||
| 121 | + { | ||
| 122 | + sptr<WantFdValue> value = WantFdValue::Borrow(fd); | ||
| 123 | + ASSERT_NE(value, nullptr); | ||
| 124 | + EXPECT_FALSE(value->IsOwned()); | ||
| 125 | + EXPECT_EQ(fd, value->GetFd()); | ||
| 126 | + } | ||
| 127 | + EXPECT_NE(-1, fcntl(fd, F_GETFD)); | ||
| 128 | + close(fd); | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +HWTEST_F(WantFdAdapterTest, Holder_FdZeroValid, TestSize.Level1) | ||
| 132 | +{ | ||
| 133 | + sptr<WantFdValue> value = WantFdValue::Adopt(0); | ||
| 134 | + ASSERT_NE(value, nullptr); | ||
| 135 | + EXPECT_EQ(0, value->GetFd()); | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +HWTEST_F(WantFdAdapterTest, Holder_NegativeFdRejected, TestSize.Level1) | ||
| 139 | +{ | ||
| 140 | + sptr<WantFdValue> value = WantFdValue::Adopt(-1); | ||
| 141 | + EXPECT_EQ(value, nullptr); | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +HWTEST_F(WantFdAdapterTest, Value_CopySharesValue, TestSize.Level1) | ||
| 145 | +{ | ||
| 146 | + int fd = CreatePipeFd(); | ||
| 147 | + ASSERT_GE(fd, 0); | ||
| 148 | + sptr<IInteger> val1 = WantFdValue::Adopt(fd); | ||
| 149 | + IWantFdValue *fdVal1 = IWantFdValue::Query(IInteger::Query(val1)); | ||
| 150 | + ASSERT_NE(fdVal1, nullptr); | ||
| 151 | + EXPECT_EQ(fd, fdVal1->GetFd()); | ||
| 152 | + sptr<IInteger> val2 = val1; | ||
| 153 | + val1 = nullptr; | ||
| 154 | + EXPECT_NE(-1, fcntl(fd, F_GETFD)); | ||
| 155 | + val2 = nullptr; | ||
| 156 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 157 | +} | ||
| 158 | + | ||
| 159 | +HWTEST_F(WantFdAdapterTest, Value_IWantFdValueQuery, TestSize.Level1) | ||
| 160 | +{ | ||
| 161 | + int fd = CreatePipeFd(); | ||
| 162 | + ASSERT_GE(fd, 0); | ||
| 163 | + sptr<IInteger> val = WantFdValue::Adopt(fd); | ||
| 164 | + IInteger *iInt = IInteger::Query(val); | ||
| 165 | + ASSERT_NE(iInt, nullptr); | ||
| 166 | + IWantFdValue *fdVal = IWantFdValue::Query(iInt); | ||
| 167 | + ASSERT_NE(fdVal, nullptr); | ||
| 168 | + EXPECT_EQ(fd, fdVal->GetFd()); | ||
| 169 | + EXPECT_TRUE(fdVal->IsOwned()); | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | +HWTEST_F(WantFdAdapterTest, SetOwnedFd_CreatesFdMarker, TestSize.Level1) | ||
| 173 | +{ | ||
| 174 | + int fd = CreatePipeFd(); | ||
| 175 | + ASSERT_GE(fd, 0); | ||
| 176 | + WantParams params; | ||
| 177 | + EXPECT_TRUE(WantFdAdapter::SetOwnedFd(params, "test_fd", fd)); | ||
| 178 | + EXPECT_TRUE(params.HasParam("test_fd")); | ||
| 179 | + EXPECT_EQ(fd, params.fds_["test_fd"]); | ||
| 180 | + int extractedFd = -1; | ||
| 181 | + EXPECT_TRUE(WantFdAdapter::TryExtractFd(params.GetParam("test_fd"), extractedFd)); | ||
| 182 | + EXPECT_EQ(fd, extractedFd); | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +HWTEST_F(WantFdAdapterTest, SetBorrowedFd_CreatesFdMarker, TestSize.Level1) | ||
| 186 | +{ | ||
| 187 | + int fd = CreatePipeFd(); | ||
| 188 | + ASSERT_GE(fd, 0); | ||
| 189 | + WantParams params; | ||
| 190 | + EXPECT_TRUE(WantFdAdapter::SetBorrowedFd(params, "borrow_fd", fd)); | ||
| 191 | + EXPECT_TRUE(params.HasParam("borrow_fd")); | ||
| 192 | + EXPECT_EQ(fd, params.fds_["borrow_fd"]); | ||
| 193 | + close(fd); | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +HWTEST_F(WantFdAdapterTest, SetOwnedFd_NegativeFdIgnored, TestSize.Level1) | ||
| 197 | +{ | ||
| 198 | + WantParams params; | ||
| 199 | + EXPECT_FALSE(WantFdAdapter::SetOwnedFd(params, "bad_fd", -1)); | ||
| 200 | + EXPECT_FALSE(params.HasParam("bad_fd")); | ||
| 201 | +} | ||
| 202 | + | ||
| 203 | +HWTEST_F(WantFdAdapterTest, SetBorrowedFd_NegativeFdIgnored, TestSize.Level1) | ||
| 204 | +{ | ||
| 205 | + WantParams params; | ||
| 206 | + EXPECT_FALSE(WantFdAdapter::SetBorrowedFd(params, "bad_fd", -1)); | ||
| 207 | + EXPECT_FALSE(params.HasParam("bad_fd")); | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +HWTEST_F(WantFdAdapterTest, SetOwnedFd_FailureLeavesParamsUnchanged, TestSize.Level1) | ||
| 211 | +{ | ||
| 212 | + WantParams params; | ||
| 213 | + params.SetParam("keep", String::Box("v")); | ||
| 214 | + EXPECT_FALSE(WantFdAdapter::SetOwnedFd(params, "bad_fd", -1)); | ||
| 215 | + EXPECT_FALSE(params.HasParam("bad_fd")); | ||
| 216 | + EXPECT_TRUE(params.HasParam("keep")); | ||
| 217 | +} | ||
| 218 | + | ||
| 219 | +HWTEST_F(WantFdAdapterTest, DestructorReleasesHolder, TestSize.Level1) | ||
| 220 | +{ | ||
| 221 | + int fd = CreatePipeFd(); | ||
| 222 | + ASSERT_GE(fd, 0); | ||
| 223 | + { | ||
| 224 | + WantParams params; | ||
| 225 | + WantFdAdapter::SetOwnedFd(params, "fd_key", fd); | ||
| 226 | + EXPECT_TRUE(params.HasParam("fd_key")); | ||
| 227 | + } | ||
| 228 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 229 | +} | ||
| 230 | + | ||
| 231 | +HWTEST_F(WantFdAdapterTest, CopySharesHolderNoDup, TestSize.Level1) | ||
| 232 | +{ | ||
| 233 | + int fd = CreatePipeFd(); | ||
| 234 | + ASSERT_GE(fd, 0); | ||
| 235 | + { | ||
| 236 | + WantParams original; | ||
| 237 | + WantFdAdapter::SetOwnedFd(original, "fd_key", fd); | ||
| 238 | + WantParams copy = original; | ||
| 239 | + EXPECT_TRUE(copy.HasParam("fd_key")); | ||
| 240 | + EXPECT_EQ(fd, copy.fds_["fd_key"]); | ||
| 241 | + } | ||
| 242 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 243 | +} | ||
| 244 | + | ||
| 245 | +HWTEST_F(WantFdAdapterTest, CopyDoesNotCloseOriginal, TestSize.Level1) | ||
| 246 | +{ | ||
| 247 | + int fd = CreatePipeFd(); | ||
| 248 | + ASSERT_GE(fd, 0); | ||
| 249 | + { | ||
| 250 | + WantParams original; | ||
| 251 | + WantFdAdapter::SetOwnedFd(original, "fd_key", fd); | ||
| 252 | + { | ||
| 253 | + WantParams copy = original; | ||
| 254 | + } | ||
| 255 | + EXPECT_NE(-1, fcntl(fd, F_GETFD)); | ||
| 256 | + } | ||
| 257 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +HWTEST_F(WantFdAdapterTest, CloseAllFdReleasesHolder, TestSize.Level1) | ||
| 261 | +{ | ||
| 262 | + int fd = CreatePipeFd(); | ||
| 263 | + ASSERT_GE(fd, 0); | ||
| 264 | + WantParams params; | ||
| 265 | + WantFdAdapter::SetOwnedFd(params, "fd_key", fd); | ||
| 266 | + params.CloseAllFd(); | ||
| 267 | + EXPECT_FALSE(params.HasParam("fd_key")); | ||
| 268 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +HWTEST_F(WantFdAdapterTest, RemoveAllFdSameAsCloseAllFd, TestSize.Level1) | ||
| 272 | +{ | ||
| 273 | + int fd = CreatePipeFd(); | ||
| 274 | + ASSERT_GE(fd, 0); | ||
| 275 | + WantParams params; | ||
| 276 | + WantFdAdapter::SetOwnedFd(params, "fd_key", fd); | ||
| 277 | + params.RemoveAllFd(); | ||
| 278 | + EXPECT_FALSE(params.HasParam("fd_key")); | ||
| 279 | + EXPECT_EQ(-1, fcntl(fd, F_GETFD)); | ||
| 280 | +} | ||
| 281 | + | ||
| 282 | +HWTEST_F(WantFdAdapterTest, StripDoesNotCloseOriginal, TestSize.Level1) | ||
| 283 | +{ | ||
| 284 | + int fd = CreatePipeFd(); | ||
| 285 | + ASSERT_GE(fd, 0); | ||
| 286 | + WantParams original; | ||
| 287 | + WantFdAdapter::SetOwnedFd(original, "fd_key", fd); | ||
| 288 | + { | ||
| 289 | + WantParams copy = original; | ||
| 290 | + copy.RemoveAllFd(); | ||
| 291 | + EXPECT_FALSE(copy.HasParam("fd_key")); | ||
| 292 | + } | ||
| 293 | + EXPECT_NE(-1, fcntl(fd, F_GETFD)); | ||
| 294 | +} | ||
| 295 | +} | ||
| 296 | +} | ||