• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "ani_common_want.h"
17 #include "ani_common_util.h"
18 #include "array_wrapper.h"
19 #include "bool_wrapper.h"
20 #include "byte_wrapper.h"
21 #include "double_wrapper.h"
22 #include "float_wrapper.h"
23 #include "hilog_tag_wrapper.h"
24 #include "int_wrapper.h"
25 #include "ipc_skeleton.h"
26 #include "js_runtime_utils.h"
27 #include "long_wrapper.h"
28 #include "napi_remote_object.h"
29 #include "remote_object_wrapper.h"
30 #include "short_wrapper.h"
31 #include "string_wrapper.h"
32 #include "tokenid_kit.h"
33 #include "want_params_wrapper.h"
34 #include "zchar_wrapper.h"
35 
36 namespace OHOS {
37 namespace AppExecFwk {
38 using namespace OHOS::AbilityRuntime;
39 namespace {
40 constexpr const char* ABILITY_WANT_CLASS_NAME = "L@ohos/app/ability/Want/Want;";
41 constexpr const char* TOOL_CLASS_NAME = "L@ohos/app/ability/Want/RecordSerializeTool;";
42 constexpr const char* INNER_CLASS_NAME = "Lability/abilityResult/AbilityResultInner;";
43 constexpr const char* ELEMENTNAME_CLASS_NAME = "LbundleManager/ElementNameInner/ElementNameInner;";
44 
InnerWrapWantParams(ani_env * env,ani_class wantCls,ani_object wantObject,const AAFwk::WantParams & wantParams)45 bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams)
46 {
47     ani_ref wantParamRef = WrapWantParams(env, wantParams);
48     if (wantParamRef == nullptr) {
49         TAG_LOGE(AAFwkTag::ANI, "failed to WrapWantParams");
50         return false;
51     }
52     return SetFieldRefByName(env, wantCls, wantObject, "parameters", wantParamRef);
53 }
54 
InnerUnwrapWantParams(ani_env * env,ani_object wantObject,AAFwk::WantParams & wantParams)55 bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParams& wantParams)
56 {
57     ani_ref wantParamRef = nullptr;
58     if (!GetFieldRefByName(env, wantObject, "parameters", wantParamRef)) {
59         TAG_LOGE(AAFwkTag::ANI, "failed to get want parameter");
60         return false;
61     }
62     return UnwrapWantParams(env, wantParamRef, wantParams);
63 }
64 }
65 
WrapWant(ani_env * env,const AAFwk::Want & want)66 ani_object WrapWant(ani_env *env, const AAFwk::Want &want)
67 {
68     TAG_LOGD(AAFwkTag::ANI, "WrapWant called");
69     if (env == nullptr) {
70         TAG_LOGE(AAFwkTag::ANI, "null env");
71         return nullptr;
72     }
73     ani_class cls = nullptr;
74     ani_status status = ANI_ERROR;
75     ani_method method = nullptr;
76     ani_object object = nullptr;
77     if ((status = env->FindClass(ABILITY_WANT_CLASS_NAME, &cls)) != ANI_OK) {
78         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
79         return nullptr;
80     }
81     if (cls == nullptr) {
82         TAG_LOGE(AAFwkTag::ANI, "null wantCls");
83         return nullptr;
84     }
85     if ((status = env->Class_FindMethod(cls, "<ctor>", ":V", &method)) != ANI_OK) {
86         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
87         return nullptr;
88     }
89     if ((status = env->Object_New(cls, method, &object)) != ANI_OK) {
90         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
91         return nullptr;
92     }
93     if (object == nullptr) {
94         TAG_LOGE(AAFwkTag::ANI, "null object");
95         return nullptr;
96     }
97 
98     auto elementName = want.GetElement();
99     SetFieldStringByName(env, cls, object, "deviceId", elementName.GetDeviceID());
100     SetFieldStringByName(env, cls, object, "bundleName", elementName.GetBundleName());
101     SetFieldStringByName(env, cls, object, "abilityName", elementName.GetAbilityName());
102     SetFieldStringByName(env, cls, object, "moduleName", elementName.GetModuleName());
103     SetFieldStringByName(env, cls, object, "uri", want.GetUriString());
104     SetFieldStringByName(env, cls, object, "type", want.GetType());
105     SetFieldDoubleByName(env, cls, object, "flags", want.GetFlags());
106     SetFieldStringByName(env, cls, object, "action", want.GetAction());
107     InnerWrapWantParams(env, cls, object, want.GetParams());
108     SetFieldArrayStringByName(env, cls, object, "entities", want.GetEntities());
109 
110     return object;
111 }
112 
WrapWantParams(ani_env * env,const AAFwk::WantParams & wantParams)113 ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams)
114 {
115     if (env == nullptr) {
116         TAG_LOGE(AAFwkTag::ANI, "null env");
117         return nullptr;
118     }
119     ani_status status = ANI_ERROR;
120     ani_class cls = nullptr;
121     if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) {
122         TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status);
123         return nullptr;
124     }
125     if (cls == nullptr) {
126         TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null");
127         return nullptr;
128     }
129     ani_static_method parseNoThrowMethod = nullptr;
130     status = env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseNoThrowMethod);
131     if (status != ANI_OK) {
132         TAG_LOGE(AAFwkTag::ANI, "failed to get parseNoThrow method, status: %{public}d", status);
133         return nullptr;
134     }
135 
136     nlohmann::json wantParamsJson = wantParams;
137     std::string wantParamsString = wantParamsJson.dump();
138     ani_string wantParamsAniString;
139     status = env->String_NewUTF8(wantParamsString.c_str(), wantParamsString.length(), &wantParamsAniString);
140     if (status != ANI_OK) {
141         TAG_LOGE(AAFwkTag::ANI, "String_NewUTF8 wantParamsString failed, status: %{public}d", status);
142         return nullptr;
143     }
144 
145     ani_ref wantParamsRef = nullptr;
146     status = env->Class_CallStaticMethod_Ref(cls, parseNoThrowMethod, &wantParamsRef, wantParamsAniString);
147     if (status != ANI_OK) {
148         TAG_LOGE(AAFwkTag::ANI, "failed to call parseNoThrow method, status: %{public}d", status);
149         return nullptr;
150     }
151     return wantParamsRef;
152 }
153 
InnerWrapWantParamsString(ani_env * env,ani_object object,const std::string & key,const AAFwk::WantParams & wantParams)154 bool InnerWrapWantParamsString(
155     ani_env *env, ani_object object, const std::string &key, const AAFwk::WantParams &wantParams)
156 {
157     if (env == nullptr) {
158         TAG_LOGE(AAFwkTag::ANI, "null env");
159         return false;
160     }
161     auto value = wantParams.GetParam(key);
162     AAFwk::IString *ao = AAFwk::IString::Query(value);
163     return ao != nullptr;
164 }
165 
UnwrapElementName(ani_env * env,ani_object param,ElementName & elementName)166 bool UnwrapElementName(ani_env *env, ani_object param, ElementName &elementName)
167 {
168     if (env == nullptr) {
169         TAG_LOGE(AAFwkTag::ANI, "null env");
170         return false;
171     }
172     std::string deviceId;
173     if (GetFieldStringByName(env, param, "deviceId", deviceId)) {
174         elementName.SetDeviceID(deviceId);
175     }
176 
177     std::string bundleName;
178     if (GetFieldStringByName(env, param, "bundleName", bundleName)) {
179         elementName.SetBundleName(bundleName);
180     }
181 
182     std::string abilityName;
183     if (GetFieldStringByName(env, param, "abilityName", abilityName)) {
184         elementName.SetAbilityName(abilityName);
185     }
186 
187     std::string moduleName;
188     if (GetFieldStringByName(env, param, "moduleName", moduleName)) {
189         elementName.SetModuleName(moduleName);
190     }
191     return true;
192 }
193 
UnwrapWant(ani_env * env,ani_object param,AAFwk::Want & want)194 bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want)
195 {
196     TAG_LOGD(AAFwkTag::ANI, "UnwrapWant called");
197     if (env == nullptr) {
198         TAG_LOGE(AAFwkTag::ANI, "null env");
199         return false;
200     }
201     std::string action;
202     if (GetFieldStringByName(env, param, "action", action)) {
203         TAG_LOGD(AAFwkTag::ANI, "action %{public}s", action.c_str());
204         want.SetAction(action);
205     }
206 
207     std::string uri = "";
208     if (GetFieldStringByName(env, param, "uri", uri)) {
209         TAG_LOGD(AAFwkTag::ANI, "uri %{public}s", uri.c_str());
210         want.SetUri(uri);
211     }
212 
213     double flags = 0.0;
214     if (GetFieldDoubleByName(env, param, "flags", flags)) {
215         TAG_LOGD(AAFwkTag::ANI, "flags %{public}f", flags);
216         want.SetFlags(static_cast<int>(flags));
217     }
218 
219     std::string type = "";
220     if (GetFieldStringByName(env, param, "type", type)) {
221         TAG_LOGD(AAFwkTag::ANI, "type %{public}s", type.c_str());
222         want.SetType(type);
223     }
224 
225     ElementName natElementName;
226     UnwrapElementName(env, param, natElementName);
227     want.SetElementName(natElementName.GetDeviceID(), natElementName.GetBundleName(), natElementName.GetAbilityName(),
228         natElementName.GetModuleName());
229 
230     std::vector<std::string> valueStringList;
231     if (GetFieldStringArrayByName(env, param, "entities", valueStringList)) {
232         for (size_t i = 0; i < valueStringList.size(); i++) {
233             want.AddEntity(valueStringList[i]);
234         }
235     }
236     TAG_LOGD(AAFwkTag::ANI,
237         "DeviceID %{public}s, BundleName %{public}s, AbilityName %{public}s, ModuleName %{public}s",
238         natElementName.GetDeviceID().c_str(), natElementName.GetBundleName().c_str(),
239         natElementName.GetAbilityName().c_str(), natElementName.GetModuleName().c_str());
240 
241     AAFwk::WantParams wantParams;
242     if (InnerUnwrapWantParams(env, param, wantParams)) {
243         want.SetParams(wantParams);
244     }
245     return true;
246 }
247 
UnwrapWantParams(ani_env * env,ani_ref param,AAFwk::WantParams & wantParams)248 bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams)
249 {
250     if (env == nullptr) {
251         TAG_LOGE(AAFwkTag::ANI, "null env");
252         return false;
253     }
254     ani_status status = ANI_ERROR;
255     ani_class cls = nullptr;
256     if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) {
257         TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status);
258         return false;
259     }
260     if (cls == nullptr) {
261         TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null");
262         return false;
263     }
264     ani_static_method stringifyMethod = nullptr;
265     status = env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod);
266     if (status != ANI_OK) {
267         TAG_LOGE(AAFwkTag::ANI, "failed to get stringifyNoThrow method, status: %{public}d", status);
268         return false;
269     }
270     ani_ref wantParamsAniString;
271     status = env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &wantParamsAniString, param);
272     if (status != ANI_OK) {
273         TAG_LOGE(AAFwkTag::ANI, "failed to call stringifyNoThrow method, status: %{public}d", status);
274         return false;
275     }
276     std::string wantParamsString;
277     if (!GetStdString(env, reinterpret_cast<ani_string>(wantParamsAniString), wantParamsString)) {
278         TAG_LOGE(AAFwkTag::ANI, "GetStdString failed");
279         return false;
280     }
281     if (wantParamsString.empty()) {
282         TAG_LOGE(AAFwkTag::ANI, "wantParamsString empty");
283         return false;
284     }
285     nlohmann::json wantParamsJson = nlohmann::json::parse(wantParamsString, nullptr, false);
286     if (wantParamsJson.is_discarded()) {
287         TAG_LOGE(AAFwkTag::ANI, "Failed to parse json string");
288         return false;
289     }
290     from_json(wantParamsJson, wantParams);
291     return true;
292 }
293 
GetAbilityResultClass(ani_env * env,ani_class & cls)294 bool GetAbilityResultClass(ani_env *env, ani_class &cls)
295 {
296     ani_status status = env->FindClass(INNER_CLASS_NAME, &cls);
297     if (status != ANI_OK || cls == nullptr) {
298         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
299         return false;
300     }
301     return true;
302 }
303 
GetResultCode(ani_env * env,ani_object param,ani_class cls,int & resultCode)304 bool GetResultCode(ani_env *env, ani_object param, ani_class cls, int &resultCode)
305 {
306     ani_method method = nullptr;
307     ani_status status = env->Class_FindMethod(cls, "<get>resultCode", nullptr, &method);
308     if (status != ANI_OK) {
309         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
310         return false;
311     }
312     ani_double dResultCode = 0.0;
313     status = env->Object_CallMethod_Double(param, method, &dResultCode);
314     if (status != ANI_OK) {
315         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
316         return false;
317     }
318     resultCode = static_cast<int>(dResultCode);
319     return true;
320 }
321 
GetWantReference(ani_env * env,ani_object param,ani_class cls,ani_ref & wantRef)322 bool GetWantReference(ani_env *env, ani_object param, ani_class cls, ani_ref &wantRef)
323 {
324     ani_method method {};
325     ani_status status = env->Class_FindMethod(cls, "<get>want", nullptr, &method);
326     if (status != ANI_OK) {
327         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
328         return false;
329     }
330     status = env->Object_CallMethod_Ref(param, method, &wantRef);
331     if (status != ANI_OK) {
332         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
333         return false;
334     }
335     ani_boolean isUndefined = ANI_TRUE;
336     status = env->Reference_IsUndefined(wantRef, &isUndefined);
337     if (status != ANI_OK || isUndefined) {
338         TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
339         return false;
340     }
341     return true;
342 }
343 
UnWrapAbilityResult(ani_env * env,ani_object param,int & resultCode,AAFwk::Want & want)344 bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want)
345 {
346     TAG_LOGD(AAFwkTag::ANI, "called");
347     if (env == nullptr) {
348         TAG_LOGE(AAFwkTag::ANI, "null env");
349         return false;
350     }
351     ani_class cls = nullptr;
352     if (!GetAbilityResultClass(env, cls)) {
353         return false;
354     }
355     if (!GetResultCode(env, param, cls, resultCode)) {
356         return false;
357     }
358     ani_ref wantRef = nullptr;
359     if (!GetWantReference(env, param, cls, wantRef)) {
360         return false;
361     }
362     return UnwrapWant(env, reinterpret_cast<ani_object>(wantRef), want);
363 }
364 
WrapElementName(ani_env * env,const AppExecFwk::ElementName & elementNameParam)365 ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam)
366 {
367     TAG_LOGD(AAFwkTag::ANI, "WrapElementName");
368     if (env == nullptr) {
369         TAG_LOGE(AAFwkTag::ANI, "null env");
370         return nullptr;
371     }
372     ani_class elementNameObj = nullptr;
373     ani_status status = ANI_ERROR;
374     ani_method method = nullptr;
375     ani_object object = nullptr;
376     if ((status = env->FindClass(ELEMENTNAME_CLASS_NAME, &elementNameObj)) != ANI_OK || elementNameObj == nullptr) {
377         TAG_LOGE(AAFwkTag::ANI, "FindClass status: %{public}d or null elementNameObj", status);
378         return nullptr;
379     }
380     if ((status = env->Class_FindMethod(elementNameObj, "<ctor>", ":V", &method)) != ANI_OK || method == nullptr) {
381         TAG_LOGE(AAFwkTag::ANI, "Class_FindMethod status: %{public}d or null method", status);
382         return nullptr;
383     }
384     if ((status = env->Object_New(elementNameObj, method, &object)) != ANI_OK || object == nullptr) {
385         TAG_LOGE(AAFwkTag::ANI, "Object_New status: %{public}d or null object", status);
386         return nullptr;
387     }
388     return WrapElementNameInner(env, elementNameObj, object, elementNameParam);
389 }
390 
WrapElementNameInner(ani_env * env,ani_class elementNameObj,ani_object object,const AppExecFwk::ElementName & elementNameParam)391 ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object,
392     const AppExecFwk::ElementName &elementNameParam)
393 {
394     TAG_LOGD(AAFwkTag::ANI, "WrapElementNameInner");
395     if (env == nullptr || elementNameObj == nullptr || object == nullptr) {
396         TAG_LOGE(AAFwkTag::ANI, "invalid args");
397         return nullptr;
398     }
399     if (!SetFieldStringByName(env, elementNameObj, object, "bundleName", elementNameParam.GetBundleName())) {
400         TAG_LOGE(AAFwkTag::ANI, "set bundleName failed");
401         return nullptr;
402     }
403     if (!SetFieldStringByName(env, elementNameObj, object, "abilityName", elementNameParam.GetAbilityName())) {
404         TAG_LOGE(AAFwkTag::ANI, "set abilityName failed");
405         return nullptr;
406     }
407     if (!SetFieldStringByName(env, elementNameObj, object, "deviceId", elementNameParam.GetDeviceID())) {
408         TAG_LOGE(AAFwkTag::ANI, "set deviceId failed");
409     }
410     if (!SetFieldStringByName(env, elementNameObj, object, "moduleName", elementNameParam.GetModuleName())) {
411         TAG_LOGE(AAFwkTag::ANI, "set moduleName failed");
412     }
413     if (!SetFieldStringByName(env, elementNameObj, object, "uri", elementNameParam.GetURI())) {
414         TAG_LOGE(AAFwkTag::ANI, "set uri failed");
415     }
416     if (!SetFieldStringByName(env, elementNameObj, object, "shortName", elementNameParam.GetURI())) {
417         TAG_LOGE(AAFwkTag::ANI, "set shortName failed");
418     }
419     return object;
420 }
421 
422 } // namespace AppExecFwk
423 } // namespace OHOS
424