From aaed6d10cb60ce34785e7a942e8e14fea95f4f6c Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Sat, 7 Jun 2025 17:19:57 +0800 Subject: [PATCH] add ani common Signed-off-by: zhangzezhong --- bundle.json | 12 + frameworks/ets/ani/BUILD.gn | 21 + frameworks/ets/ani/ani_common/BUILD.gn | 79 +++ .../include/ani_common_start_options.h | 27 + .../ani/ani_common/include/ani_common_util.h | 48 ++ .../ani/ani_common/include/ani_common_want.h | 38 ++ .../src/ani_common_start_options.cpp | 43 ++ .../ani/ani_common/src/ani_common_util.cpp | 529 ++++++++++++++++++ .../ani/ani_common/src/ani_common_want.cpp | 337 +++++++++++ services/common/include/hilog_tag_wrapper.h | 5 +- 10 files changed, 1138 insertions(+), 1 deletion(-) create mode 100644 frameworks/ets/ani/BUILD.gn create mode 100644 frameworks/ets/ani/ani_common/BUILD.gn create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_start_options.h create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_util.h create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_want.h create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_util.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_want.cpp diff --git a/bundle.json b/bundle.json index 38fc7eb4e9a..fb0a91e234c 100644 --- a/bundle.json +++ b/bundle.json @@ -128,6 +128,7 @@ "//foundation/ability/ability_runtime/frameworks/native/insight_intent:insight_intent_innerkits", "//foundation/ability/ability_runtime/frameworks/c/ability_runtime:ability_runtime", "//foundation/ability/ability_runtime/frameworks/cj:cj_ability_packages", + "//foundation/ability/ability_runtime/frameworks/ets/ani:ani_packages", "//foundation/ability/ability_runtime/frameworks/js/napi:napi_packages", "//foundation/ability/ability_runtime/cj_environment/frameworks/cj_environment:cj_environment", "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment", @@ -289,6 +290,17 @@ }, "name": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_common:napi_common" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_common/include", + "header_files": [ + "ani_common_start_options.h", + "ani_common_util.h", + "ani_common_want.h" + ] + }, + "name": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_common:ani_common" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_ability_common", diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn new file mode 100644 index 00000000000..c1c6b1870d8 --- /dev/null +++ b/frameworks/ets/ani/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +group("ani_packages") { + deps = [ + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] +} diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn new file mode 100644 index 00000000000..aecd68ca122 --- /dev/null +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -0,0 +1,79 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +config("ani_common_public_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +ohos_shared_library("ani_common") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_services_path}/common/include", + ] + + public_configs = [ ":ani_common_public_config" ] + + sources = [ + "src/ani_common_start_options.cpp", + "src/ani_common_util.cpp", + "src/ani_common_want.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + ] + + external_deps = [ + "ability_base:base", + "ability_base:session_info", + "ability_base:want", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "json:nlohmann_json_static", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ani_common/include/ani_common_start_options.h b/frameworks/ets/ani/ani_common/include/ani_common_start_options.h new file mode 100644 index 00000000000..f0e66d58937 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_start_options.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_COMMON_START_OPTIONS_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_START_OPTIONS_H + +#include "start_options.h" +#include "ani_common_util.h" +namespace OHOS { +namespace AppExecFwk { +bool UnwrapStartOptionsWithProcessOption(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); +bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_START_OPTIONS_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_util.h b/frameworks/ets/ani/ani_common/include/ani_common_util.h new file mode 100644 index 00000000000..55596ed2a69 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H + +#include "ani.h" + +namespace OHOS { +namespace AppExecFwk { +bool GetDoubleOrUndefined(ani_env *env, ani_object param, const char *name, ani_double &value); +bool GetBoolOrUndefined(ani_env *env, ani_object param, const char *name); +bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std::string &res); +bool GetIntByName(ani_env *env, ani_object param, const char *name, int &value); +bool GetStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res); +bool GetStdString(ani_env *env, ani_string str, std::string &res); + +ani_string GetAniString(ani_env *env, const std::string &str); +ani_array_ref GetAniArrayString(ani_env *env, const std::vector &values); +bool GetRefFieldByName(ani_env *env, ani_object param, const char *name, ani_ref &ref); + +ani_object CreateDouble(ani_env *env, ani_double value); +ani_object CreateBoolean(ani_env *env, ani_boolean value); + +bool SetFieldString(ani_env *env, ani_class cls, ani_object object, + const std::string &fieldName, const std::string &value); +bool SetFieldDouble(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, double value); +bool SetFieldBoolean(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, bool value); +bool SetFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value); +bool SetFieldArrayString(ani_env *env, ani_class cls, ani_object object, + const std::string &fieldName, + const std::vector &values); +bool SetFieldRef(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, ani_ref value); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_want.h b/frameworks/ets/ani/ani_common/include/ani_common_want.h new file mode 100644 index 00000000000..60e59eaa434 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_want.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_H + +#include +#include +#include + +#include "native_engine/native_engine.h" +#include "want.h" +#include "want_params.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AppExecFwk { +ani_object WrapWant(ani_env *env, const AAFwk::Want &want); +ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams); + +bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want); +bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams); +bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_H diff --git a/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp new file mode 100644 index 00000000000..0599d38dc19 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_start_options.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +bool UnwrapStartOptionsWithProcessOption(ani_env* env, ani_object param, AAFwk::StartOptions &startOptions) +{ + UnwrapStartOptions(env, param, startOptions); + return true; +} + +bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + TAG_LOGD(AAFwkTag::ANI, "UnwrapStartOptions called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_double displayId = 0.0; + if (GetDoubleOrUndefined(env, param, "displayId", displayId)) { + startOptions.SetDisplayID(static_cast(displayId)); + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp new file mode 100644 index 00000000000..bb3cf12338b --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_util.h" + +#include +#include "hilog_tag_wrapper.h" +#include "securec.h" + +namespace OHOS { +namespace AppExecFwk { +constexpr const char* CLASSNAME_DOUBLE = "Lstd/core/Double;"; +constexpr const char* CLASSNAME_BOOLEAN = "Lstd/core/Boolean;"; + +bool GetIntByName(ani_env *env, ani_object param, const char *name, int &value) +{ + ani_int res; + ani_status status; + + status = env->Object_GetFieldByName_Int(param, name, &res); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + value = static_cast(res); + return true; +} + +bool GetDoubleOrUndefined(ani_env *env, ani_object param, const char *name, ani_double &value) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Object_CallMethodByName_Double( + reinterpret_cast(obj), "doubleValue", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; +} + +bool GetBoolOrUndefined(ani_env *env, ani_object param, const char *name) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + ani_boolean res = 0.0; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return res; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return res; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return res; + } + if ((status = env->Object_CallMethodByName_Boolean( + reinterpret_cast(obj), "booleanValue", nullptr, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return res; + } + return res; +} + +bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std::string &res) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + if (!GetStdString(env, reinterpret_cast(obj), res)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed"); + return false; + } + return true; +} + +bool GetFixedStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status; + ani_size size = 0; + ani_size i; + ani_ref ref; + std::string str; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + + if ((status = env->Array_GetLength(reinterpret_cast(obj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + for (i = 0; i < size; i++) { + if ((status = env->Array_Get_Ref(reinterpret_cast(obj), i, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d, index: %{public}zu", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed, index: %{public}zu", i); + return false; + } + + res.push_back(str); + } + + return true; +} + +bool SetFieldFixedArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::vector &values) +{ + ani_field field = nullptr; + ani_array_ref array = nullptr; + ani_class stringCls = nullptr; + ani_string string = nullptr; + ani_ref undefinedRef = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->FindClass("Lstd/core/String;", &stringCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->GetUndefined(&undefinedRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->Array_New_Ref(stringCls, values.size(), undefinedRef, &array); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); ++i) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + status = env->Array_Set_Ref(array, i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + } + status = env->Object_SetField_Ref(object, field, array); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; +} + +bool GetStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res) +{ + ani_ref arrayObj = nullptr; + ani_boolean isUndefined = true; + ani_status status; + ani_double length; + std::string str; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(arrayObj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + + status = env->Object_GetPropertyByName_Double(reinterpret_cast(arrayObj), "length", &length); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + for (int i = 0; i < static_cast(length); i++) { + ani_ref stringEntryRef; + status = env->Object_CallMethodByName_Ref(reinterpret_cast(arrayObj), + "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d, index: %{public}d", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(stringEntryRef), str)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed, index: %{public}d", i); + return false; + } + + res.push_back(str); + TAG_LOGD(AAFwkTag::ANI, "GetStdString index: %{public}d %{public}s", i, str.c_str()); + } + + return true; +} + + +bool SetFieldArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::vector &values) +{ + ani_field field = nullptr; + ani_class arrayCls = nullptr; + ani_method arrayCtor; + ani_object arrayObj; + ani_string string = nullptr; + + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->FindClass("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + } + status = env->Object_SetField_Ref(object, field, arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + return true; +} + +bool GetStdString(ani_env *env, ani_string str, std::string &res) +{ + ani_size sz {}; + ani_status status = ANI_ERROR; + if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + res.resize(sz + 1); + if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + res.resize(sz); + return true; +} + +ani_string GetAniString(ani_env *env, const std::string &str) +{ + ani_string aniStr = nullptr; + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + return aniStr; +} + +ani_array_ref GetAniArrayString(ani_env *env, const std::vector &values) +{ + ani_array_ref aArrayRef = nullptr; + return aArrayRef; +} + +bool GetRefFieldByName(ani_env *env, ani_object param, const char *name, ani_ref &ref) +{ + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Ref(param, name, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_GetFieldByName_Ref failed, status : %{public}d", status); + return false; + } + + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(ref, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Reference_IsUndefined failed, status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "wantParams is undefined"); + return false; + } + return true; +} + +ani_object CreateDouble(ani_env *env, ani_double value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_DOUBLE, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "D:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} + +ani_object CreateBoolean(ani_env *env, ani_boolean value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_BOOLEAN, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "Z:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} + +bool SetFieldString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::string &value) +{ + TAG_LOGD(AAFwkTag::ANI, "fieldName : %{public}s", fieldName.c_str()); + ani_field field = nullptr; + ani_string string = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + if (value.empty()) { + ani_ref nullRef = nullptr; + if ((status = env->GetNull(&nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + if ((status = env->Object_SetField_Ref(object, field, nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; + } + + if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + + if ((status = env->Object_SetField_Ref(object, field, string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetFieldDouble(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, double value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + ani_object obj = CreateDouble(env, value); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "CreateDouble failed"); + return false; + } + status = env->Object_SetField_Ref(object, field, reinterpret_cast(obj)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetFieldBoolean(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, bool value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + status = env->Object_SetField_Boolean(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "status : %{public}s", fieldName.c_str()); + return false; + } + status = env->Object_SetField_Int(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "status : %{public}s", fieldName.c_str()); + return false; + } + return true; +} + +bool SetFieldRef(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, ani_ref value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindField %{public}s failed, status: %{public}d", fieldName.c_str(), status); + return false; + } + status = env->Object_SetField_Ref(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "SetField_Ref %{public}s failed, status: %{public}d", fieldName.c_str(), status); + return false; + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp new file mode 100644 index 00000000000..51f1046416e --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_want.h" +#include "ani_common_util.h" +#include "array_wrapper.h" +#include "bool_wrapper.h" +#include "byte_wrapper.h" +#include "double_wrapper.h" +#include "float_wrapper.h" +#include "hilog_tag_wrapper.h" +#include "int_wrapper.h" +#include "ipc_skeleton.h" +#include "js_runtime_utils.h" +#include "long_wrapper.h" +#include "napi_remote_object.h" +#include "remote_object_wrapper.h" +#include "short_wrapper.h" +#include "string_wrapper.h" +#include "tokenid_kit.h" +#include "want_params_wrapper.h" +#include "zchar_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace OHOS::AbilityRuntime; +namespace { +bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams) +{ + ani_ref wantParamRef = WrapWantParams(env, wantParams); + if (wantParamRef == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "failed to WrapWantParams"); + return false; + } + return SetFieldRef(env, wantCls, wantObject, "parameters", wantParamRef); +} + +bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParams& wantParams) +{ + ani_ref wantParamRef = nullptr; + if (!GetRefFieldByName(env, wantObject, "parameters", wantParamRef)) { + TAG_LOGE(AAFwkTag::ANI, "failed to get want parameter"); + return false; + } + return UnwrapWantParams(env, wantParamRef, wantParams); +} +} + +ani_object WrapWant(ani_env *env, const AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::ANI, "WrapWant called"); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if ((status = env->FindClass("L@ohos/app/ability/Want/Want;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null wantCls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null object"); + return nullptr; + } + + auto elementName = want.GetElement(); + SetFieldString(env, cls, object, "deviceId", elementName.GetDeviceID()); + SetFieldString(env, cls, object, "bundleName", elementName.GetBundleName()); + SetFieldString(env, cls, object, "abilityName", elementName.GetAbilityName()); + SetFieldString(env, cls, object, "moduleName", elementName.GetModuleName()); + SetFieldString(env, cls, object, "uri", want.GetUriString()); + SetFieldString(env, cls, object, "type", want.GetType()); + SetFieldDouble(env, cls, object, "flags", want.GetFlags()); + SetFieldString(env, cls, object, "action", want.GetAction()); + InnerWrapWantParams(env, cls, object, want.GetParams()); + SetFieldArrayString(env, cls, object, "entities", want.GetEntities()); + + return object; +} + +ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null"); + return nullptr; + } + ani_static_method parseNoThrowMethod = nullptr; + status = env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseNoThrowMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "failed to get parseNoThrow method, status : %{public}d", status); + return nullptr; + } + + nlohmann::json wantParamsJson = wantParams; + std::string wantParamsString = wantParamsJson.dump(); + ani_string wantParamsAniString; + status = env->String_NewUTF8(wantParamsString.c_str(), wantParamsString.length(), &wantParamsAniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "String_NewUTF8 wantParamsString failed, status : %{public}d", status); + return nullptr; + } + + ani_ref wantParamsRef = nullptr; + status = env->Class_CallStaticMethod_Ref(cls, parseNoThrowMethod, &wantParamsRef, wantParamsAniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "failed to call parseNoThrow method, status : %{public}d", status); + return nullptr; + } + return wantParamsRef; +} + +bool InnerWrapWantParamsString( + ani_env *env, ani_object object, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IString *ao = AAFwk::IString::Query(value); + if (ao == nullptr) { + return false; + } + return true; +} + +bool UnwrapElementName(ani_env *env, ani_object param, ElementName &elementName) +{ + std::string deviceId; + if (GetStringOrUndefined(env, param, "deviceId", deviceId)) { + elementName.SetDeviceID(deviceId); + } + + std::string bundleName; + if (GetStringOrUndefined(env, param, "bundleName", bundleName)) { + elementName.SetBundleName(bundleName); + } + + std::string abilityName; + if (GetStringOrUndefined(env, param, "abilityName", abilityName)) { + elementName.SetAbilityName(abilityName); + } + + std::string moduleName; + if (GetStringOrUndefined(env, param, "moduleName", moduleName)) { + elementName.SetModuleName(moduleName); + } + return true; +} + +bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::ANI, "UnwrapWant called"); + std::string action; + if (GetStringOrUndefined(env, param, "action", action)) { + TAG_LOGD(AAFwkTag::ANI, "action %{public}s", action.c_str()); + want.SetAction(action); + } + + std::string uri = ""; + if (GetStringOrUndefined(env, param, "uri", uri)) { + TAG_LOGD(AAFwkTag::ANI, "uri %{public}s", uri.c_str()); + want.SetUri(uri); + } + + ani_double flags = 0.0; + if (GetDoubleOrUndefined(env, param, "flags", flags)) { + TAG_LOGD(AAFwkTag::ANI, "flags %{public}f", flags); + want.SetFlags(static_cast(flags)); + } + + std::string type = ""; + if (GetStringOrUndefined(env, param, "type", type)) { + TAG_LOGD(AAFwkTag::ANI, "type %{public}s", type.c_str()); + want.SetType(type); + } + + ElementName natElementName; + UnwrapElementName(env, param, natElementName); + want.SetElementName(natElementName.GetDeviceID(), natElementName.GetBundleName(), natElementName.GetAbilityName(), + natElementName.GetModuleName()); + + std::vector valueStringList; + if (GetStringArrayOrUndefined(env, param, "entities", valueStringList)) { + for (size_t i = 0; i < valueStringList.size(); i++) { + want.AddEntity(valueStringList[i]); + } + } + + TAG_LOGD(AAFwkTag::ANI, + "DeviceID %{public}s, BundleName %{public}s, AbilityName %{public}s, ModuleName %{public}s", + natElementName.GetDeviceID().c_str(), natElementName.GetBundleName().c_str(), + natElementName.GetAbilityName().c_str(), natElementName.GetModuleName().c_str()); + + AAFwk::WantParams wantParams; + if (InnerUnwrapWantParams(env, param, wantParams)) { + want.SetParams(wantParams); + } + return true; +} + +bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null"); + return false; + } + + ani_static_method stringifyMethod = nullptr; + status = env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "failed to get stringifyNoThrow method, status : %{public}d", status); + return false; + } + ani_ref wantParamsAniString; + status = env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &wantParamsAniString, param); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "failed to call stringifyNoThrow method, status : %{public}d", status); + return false; + } + + std::string wantParamsString; + if (!GetStdString(env, reinterpret_cast(wantParamsAniString), wantParamsString)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed"); + return false; + } + if (wantParamsString.empty()) { + TAG_LOGE(AAFwkTag::ANI, "wantParamsString empty"); + return false; + } + nlohmann::json wantParamsJson = nlohmann::json::parse(wantParamsString, nullptr, false); + if (wantParamsJson.is_discarded()) { + TAG_LOGE(AAFwkTag::ANI, "Failed to parse json string"); + return false; + } + from_json(wantParamsJson, wantParams); + return true; +} + +bool GetAbilityResultClass(ani_env *env, ani_class &cls) +{ + ani_status status = env->FindClass("Lability/abilityResult/AbilityResultInner;", &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool GetResultCode(ani_env *env, ani_object param, ani_class cls, int &resultCode) +{ + ani_method method {}; + ani_status status = env->Class_FindMethod(cls, "resultCode", nullptr, &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_double dResultCode = 0.0; + status = env->Object_CallMethod_Double(param, method, &dResultCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + resultCode = static_cast(dResultCode); + return true; +} + +bool GetWantReference(ani_env *env, ani_object param, ani_class cls, ani_ref &wantRef) +{ + ani_method method {}; + ani_status status = env->Class_FindMethod(cls, "want", nullptr, &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + status = env->Object_CallMethod_Ref(param, method, &wantRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_boolean isUndefined = true; + status = env->Reference_IsUndefined(wantRef, &isUndefined); + if (status != ANI_OK || isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::ANI, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_class cls {}; + if (!GetAbilityResultClass(env, cls)) { + return false; + } + if (!GetResultCode(env, param, cls, resultCode)) { + return false; + } + ani_ref wantRef = nullptr; + if (!GetWantReference(env, param, cls, wantRef)) { + return false; + } + return UnwrapWant(env, reinterpret_cast(wantRef), want); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/services/common/include/hilog_tag_wrapper.h b/services/common/include/hilog_tag_wrapper.h index 29148711574..c6806808d81 100644 --- a/services/common/include/hilog_tag_wrapper.h +++ b/services/common/include/hilog_tag_wrapper.h @@ -58,6 +58,8 @@ enum class AAFwkLogTag : uint32_t { INTENT, JSNAPI, CJRUNTIME, + ETSRUNTIME, + ANI, DELEGATOR = DEFAULT + 0x30, // 0xD001330 CONTEXT, @@ -127,7 +129,8 @@ inline const char* GetDomainName1(AAFwkLogTag tag) inline const char* GetDomainName2(AAFwkLogTag tag) { - const char* tagNames[] = { "JsEnv", "JsRuntime", "FA", "Intent", "JsNapi" }; + const char* tagNames[] = { "JsEnv", "JsRuntime", "FA", "Intent", "JsNapi", + "CjRuntime", "EtsRuntime", "Ani"}; uint32_t offset = GetOffset(tag, AAFwkLogTag::JSENV); if (offset >= sizeof(tagNames) / sizeof(const char*)) { return "UN"; -- Gitee