已开启
test #872
已开启
xhz-sz创建于 9 天前
12 个文件变更+902-102
MBUILD.gn+12-1
@@ -154,7 +154,9 @@ ohos_shared_library("zuri") {
154config("want_config") {154config("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+ 
181config("want_all_dependent_config") {188config("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 
32bool Integer::Equals(IObject &other) /* [in] */32bool 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 
38std::string Integer::ToString()46std::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+#ifndef OHOS_ABILITY_BASE_WANT_FD_ADAPTER_H
16+#define OHOS_ABILITY_BASE_WANT_FD_ADAPTER_H
17+ 
18+#include <string>
19+ 
20+#include "want_params.h"
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 &params, const std::string &key, int fd);
32+ // 成功:params 保存借用视图(BORROWED),不持有 close 责任。
33+ // 失败:不关闭 fd(外部 owner 保留),params 保持原状态。返回 false。
34+ static bool SetBorrowedFd(WantParams &params, const std::string &key, int fd);
35+ 
36+private:
37+ WantFdAdapter() = delete;
38+};
39+ 
40+} // namespace AAFwk
41+} // namespace OHOS
42+ 
43+#endif // OHOS_ABILITY_BASE_WANT_FD_ADAPTER_H
@@ -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+#include "want_fd_adapter.h"
17+ 
18+#include <unistd.h>
19+ 
20+#include "ability_base_log_wrapper.h"
21+#include "int_wrapper.h"
22+#include "string_wrapper.h"
23+#include "want_fd_value.h"
24+#include "want_params_wrapper.h"
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 &params, 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 &params, 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#include "want_manager.h"16#include "want_manager.h"
17 17 
18+#include <errno.h>
18#include <map>19#include <map>
19#include <string>20#include <string>
21+#include <unistd.h>
22+#include <vector>
20#include "ability_base_log_wrapper.h"23#include "ability_base_log_wrapper.h"
21#include "bool_wrapper.h"24#include "bool_wrapper.h"
22#include "double_wrapper.h"25#include "double_wrapper.h"
23#include "int_wrapper.h"26#include "int_wrapper.h"
24#include "string_wrapper.h"27#include "string_wrapper.h"
28+#include "want_fd_adapter.h"
25#include "want_params_wrapper.h"29#include "want_params_wrapper.h"
26 30 
27namespace OHOS {31namespace 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 AAFwk156} // namespace AAFwk
161-} // namespace OHOS157+} // 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 function221 // 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+#include "want_fd_value.h"
17+ 
18+#include <new>
19+#include <unistd.h>
20+ 
21+#include "ability_base_log_wrapper.h"
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+#ifndef OHOS_ABILITY_BASE_WANT_FD_VALUE_H
16+#define OHOS_ABILITY_BASE_WANT_FD_VALUE_H
17+ 
18+#include "base_def.h"
19+#include "base_obj.h"
20+#include "int_wrapper.h"
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+#endif // OHOS_ABILITY_BASE_WANT_FD_VALUE_H
@@ -32,6 +32,8 @@
32#include "long_wrapper.h"32#include "long_wrapper.h"
33#include "nlohmann/json.hpp"33#include "nlohmann/json.hpp"
34#include "parcel.h"34#include "parcel.h"
35+#include "want_fd_value.h"
36+#include "want_fd_adapter.h"
35#include "remote_object_wrapper.h"37#include "remote_object_wrapper.h"
36#include "securec.h"38#include "securec.h"
37#include "short_wrapper.h"39#include "short_wrapper.h"
@@ -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 
359WantParams::WantParams(WantParams && other) noexcept368WantParams::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 function373+void WantParams::RebuildFdsMirror()
365-bool WantParams::NewFds(const WantParams &source, WantParams &dest)
366{374{
367- // Deep copy375+ 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 function384// inner use function
375bool WantParams::NewParams(const WantParams &source, WantParams &dest)385bool 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 
1637bool WantParams::ReadFromParcelRemoteObject(Parcel &parcel, const std::string &key)1656bool WantParams::ReadFromParcelRemoteObject(Parcel &parcel, const std::string &key)
@@ -1867,40 +1886,58 @@ void WantParams::DumpInfo(int level) const
1867 1886 
1868void WantParams::CloseAllFd()1887void 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 
1880void WantParams::RemoveAllFd()1900void WantParams::RemoveAllFd()
1881{1901{
1882- for (auto it : fds_) {1902+ CloseAllFd();
1883- params_.erase(it.first);
1884- }
1885- fds_.clear();
1886}1903}
1887 1904 
1888void WantParams::DupAllFd()1905void 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 
1906void WantParams::GetCachedUnsupportedData(std::vector<UnsupportedData> &cachedUnsupportedData) const1943void 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+ 
247ohos_unittest("want_params_wrapper_test") {274ohos_unittest("want_params_wrapper_test") {
248 module_out_path = want_output_path275 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#undef private21#undef private
22#undef protected22#undef protected
23 23 
24+#include "base_obj.h"
25+#include "string_wrapper.h"
26+ 
24using namespace OHOS;27using namespace OHOS;
25using namespace OHOS::AAFwk;28using namespace OHOS::AAFwk;
26using testing::ext::TestSize;29using testing::ext::TestSize;
27 30 
28namespace OHOS {31namespace OHOS {
29namespace AAFwk {32namespace 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+ 
30class AAfWKIntWrapperTest : public testing::Test {45class AAfWKIntWrapperTest : public testing::Test {
31public:46public:
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+#include <gtest/gtest.h>
17+#include <fcntl.h>
18+#include <unistd.h>
19+#include <utility>
20+ 
21+#define private public
22+#include "want_fd_adapter.h"
23+#undef private
24+ 
25+#include "int_wrapper.h"
26+#include "string_wrapper.h"
27+#include "want_fd_value.h"
28+#include "want_params_wrapper.h"
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+}