From 4ff3342ea487a8921c218682036772237a12c7f3 Mon Sep 17 00:00:00 2001 From: acy Date: Fri, 30 May 2025 18:30:42 +0800 Subject: [PATCH] =?UTF-8?q?driver=5Fextension=E6=95=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: acy Change-Id: I9f7054a90ba768e1f8e0fc8f521747ad2ae61def --- frameworks/BUILD.gn | 4 +- .../js/ani/driver_extension_ability/BUILD.gn | 94 ++++++ ...hos.app.ability.DriverExtensionAbility.ets | 86 +++++ .../native/include/ani_driver_extension.h | 55 ++++ .../native/include/ani_utils.h | 309 +++++++++++++++++ .../native/src/ani_driver_extension.cpp | 306 +++++++++++++++++ .../taihe/driver_extension_context/BUILD.gn | 109 ++++++ .../idl/DriverExtensionContext.taihe | 29 ++ .../include/DriverExtensionContext_ani.h | 33 ++ .../include/ani_utils.h | 310 ++++++++++++++++++ .../src/DriverExtensionContext.impl.cpp | 88 +++++ .../src/ani_constructor.cpp | 30 ++ services/native/driver_extension/BUILD.gn | 14 +- .../driver_extension/src/driver_extension.cpp | 4 +- 14 files changed, 1468 insertions(+), 3 deletions(-) create mode 100644 frameworks/js/ani/driver_extension_ability/BUILD.gn create mode 100644 frameworks/js/ani/driver_extension_ability/ets/@ohos.app.ability.DriverExtensionAbility.ets create mode 100644 frameworks/js/ani/driver_extension_ability/native/include/ani_driver_extension.h create mode 100644 frameworks/js/ani/driver_extension_ability/native/include/ani_utils.h create mode 100644 frameworks/js/ani/driver_extension_ability/native/src/ani_driver_extension.cpp create mode 100644 frameworks/js/taihe/driver_extension_context/BUILD.gn create mode 100644 frameworks/js/taihe/driver_extension_context/idl/DriverExtensionContext.taihe create mode 100644 frameworks/js/taihe/driver_extension_context/include/DriverExtensionContext_ani.h create mode 100644 frameworks/js/taihe/driver_extension_context/include/ani_utils.h create mode 100644 frameworks/js/taihe/driver_extension_context/src/DriverExtensionContext.impl.cpp create mode 100644 frameworks/js/taihe/driver_extension_context/src/ani_constructor.cpp diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 917f347..4ff45c8 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -15,6 +15,8 @@ group("ext_devmgr_frameworks") { deps = [ "ddk:ddk", "js/napi:napi_packages", - "js/taihe:device_manager_taihe" + "js/taihe:device_manager_taihe", + "js/ani/driver_extension_ability:driver_extensionAbility_ani", + "js/taihe/driver_extension_context:driverExtensionContext_taihe" ] } diff --git a/frameworks/js/ani/driver_extension_ability/BUILD.gn b/frameworks/js/ani/driver_extension_ability/BUILD.gn new file mode 100644 index 0000000..9f9b20d --- /dev/null +++ b/frameworks/js/ani/driver_extension_ability/BUILD.gn @@ -0,0 +1,94 @@ +# 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/templates/abc/ohos_abc.gni") +native_path = "../../../../services/native" +taihe_path = "../../taihe" + +generate_static_abc("driver_extension_ability_abc") { + base_url = "./ets" + files = [ + "./ets/@ohos.app.ability.DriverExtensionAbility.ets" + ] + dst_file = "$target_out_dir/driverExtensionAbility.abc" + out_puts = [ "$target_out_dir/driverExtensionAbility.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/driverExtensionAbility.abc" +} + +ohos_shared_library("driverextension_ani") { + include_dirs = [ + "native/include", + "$native_path/driver_extension/include", + "$taihe_path/driver_extension_context/include", + ] + sources = [ + "native/src/ani_driver_extension.cpp", + ] + + deps = [ + "$native_path/driver_extension:driver_extension", + "$taihe_path/driver_extension_context:driverExtensionContext_taihe" + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_connect_callback_stub", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "ability_runtime:ani_common", + "runtime_core:ani", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "ipc:ipc_napi", + "ipc:rpc_ani", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + subsystem_name = "hdf" + part_name = "external_device_manager" + output_extension = "so" +} + +ohos_prebuilt_etc("driver_extension_ability_abc_etc") { + source = "$target_out_dir/driverExtensionAbility.abc" + module_install_dir = "framework" + subsystem_name = "hdf" + part_name = "external_device_manager" + deps = [ ":driver_extension_ability_abc" ] +} + +group("driver_extensionAbility_ani") { + deps = [ + ":driver_extension_ability_abc_etc", + ":driverextension_ani" + ] +} diff --git a/frameworks/js/ani/driver_extension_ability/ets/@ohos.app.ability.DriverExtensionAbility.ets b/frameworks/js/ani/driver_extension_ability/ets/@ohos.app.ability.DriverExtensionAbility.ets new file mode 100644 index 0000000..b3c887c --- /dev/null +++ b/frameworks/js/ani/driver_extension_ability/ets/@ohos.app.ability.DriverExtensionAbility.ets @@ -0,0 +1,86 @@ +/* + * 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. + */ +/** + * @file + * @kit DriverDevelopmentKit + */ +import type rpc from '@ohos.rpc'; +import type Want from '@ohos.app.ability.Want'; +import DriverExtensionContext from 'application.DriverExtensionContext'; +import hilog from '@ohos.hilog'; + +class MyService extends rpc.RemoteObject { + constructor(descriptor: string) { + super(descriptor); + } + + public onRemoteMessageRequest( + code: number, + data: rpc.MessageSequence, + reply: rpc.MessageSequence, + options: rpc.MessageOption + ): boolean | Promise { + return false; + } +} + +export default class DriverExtensionAbility { + private callOnConnect(want: Want): rpc.RemoteObject { + let p = this.onConnect(want); + if (p instanceof Promise) { + this.isOnConnectAsync = true; + return await(p as Promise); + } else { + this.isOnConnectAsync = false; + return p; + } + } + private callOnDisConnect(want: Want) : void { + let p = this.onDisconnect(want); + if (p instanceof Promise) { + this.isOnDisconnectAsync = true; + return await(p as Promise); + } else { + this.isOnDisconnectAsync = false; + return; + } + } + onInit(want: Want): void { + hilog.info(0x0000, 'testTag', `onInit`); + } + onRelease(): void { + hilog.info(0x0000, 'testTag', `onRelease`); + } + onConnect(want: Want): rpc.RemoteObject | Promise { + hilog.info(0x0000, 'testTag', `onConnect`); + let myService: rpc.RemoteObject = new MyService("onConnect"); + return myService; + } + onDisconnect(want: Want): undefined | Promise { + hilog.info(0x0000, 'testTag', `onDisconnect`); + return undefined; + } + onDump(params: Array): Array { + hilog.info(0x0000, 'testTag', `onDump`); + return ['params']; + } + + private connectCbInfo: long = 0; + private disConnectCbInfo: long = 0; + private isOnDisconnectAsync: boolean = true; + private isOnConnectAsync: boolean = true; + remoteObject: rpc.RemoteObject | null = null; + context: DriverExtensionContext = new DriverExtensionContext(); +} diff --git a/frameworks/js/ani/driver_extension_ability/native/include/ani_driver_extension.h b/frameworks/js/ani/driver_extension_ability/native/include/ani_driver_extension.h new file mode 100644 index 0000000..f7523d2 --- /dev/null +++ b/frameworks/js/ani/driver_extension_ability/native/include/ani_driver_extension.h @@ -0,0 +1,55 @@ +/* + * 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_DRIVER_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_ANI_DRIVER_EXTENSION_H + +#include "driver_extension.h" +#include "driver_extension_context.h" +#include "runtime.h" +#include "sts_runtime.h" + +class STSRuntime; + +namespace OHOS { +namespace AbilityRuntime { +class AniDriverExtension : public DriverExtension, public std::enable_shared_from_this { +public: + explicit AniDriverExtension(STSRuntime &stsRuntime); + virtual ~AniDriverExtension() override; + static AniDriverExtension *Create(const std::unique_ptr &runtime); + virtual void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, const sptr &token) override; + virtual void OnStart(const AAFwk::Want &want) override; + virtual sptr OnConnect(const AAFwk::Want &want) override; + virtual sptr OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, bool &isAsyncCallback) override; + virtual void OnDisconnect(const AAFwk::Want &want) override; + void OnDisconnect(const AAFwk::Want &want, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, + bool &isAsyncCallback) override; + virtual void OnStop() override; + ani_array_ref ToAniStringList(ani_env *env, const std::vector ¶ms, const uint32_t length); + virtual void Dump(const std::vector ¶ms, std::vector &info) override; + void BindContext( + ani_env *env, std::shared_ptr want, const std::shared_ptr &application); + +private: + std::unique_ptr stsObj_; + STSRuntime &stsRuntime_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_DRIVER_EXTENSION_H \ No newline at end of file diff --git a/frameworks/js/ani/driver_extension_ability/native/include/ani_utils.h b/frameworks/js/ani/driver_extension_ability/native/include/ani_utils.h new file mode 100644 index 0000000..76ce63e --- /dev/null +++ b/frameworks/js/ani/driver_extension_ability/native/include/ani_utils.h @@ -0,0 +1,309 @@ +/* + * 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hilog_wrapper.h" + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...) + { + ani_object nullobj {}; + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + HILOG_ERROR("[ANI] Not found namespace %{public}s", nsName); + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + HILOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + HILOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char *clsName, ...) + { + ani_object nullobj {}; + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + HILOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + HILOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj {}; + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOG_ERROR("[ANI] Not found for class"); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + HILOG_ERROR("[ANI] Failed to Object_New for class 1"); + return nullobj; + } + return obj; + } + + template + static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T *Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); // +1 for null terminator + char *utf8_buffer = buffer.data(); + + // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; + } + + static ani_string ToAni(ani_env *env, const std::string &str) + { + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + HILOG_ERROR("[ANI] Unsupported ANI_VERSION_1"); + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) {} + + bool IsInstanceOf(const std::string &cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template + bool IsInstanceOfType(); + + template + bool TryConvert(T &value); + + template + bool TryConvertArray(std::vector &value); + +private: + ani_env *env_; + ani_object obj_; +}; + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template <> +inline bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + return true; +} + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) {} + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template + std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template <> +inline std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast(aniValue); + return value; +} + +#endif diff --git a/frameworks/js/ani/driver_extension_ability/native/src/ani_driver_extension.cpp b/frameworks/js/ani/driver_extension_ability/native/src/ani_driver_extension.cpp new file mode 100644 index 0000000..a03fbdd --- /dev/null +++ b/frameworks/js/ani/driver_extension_ability/native/src/ani_driver_extension.cpp @@ -0,0 +1,306 @@ +/* + * 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_driver_extension.h" + +#include "ability_info.h" +#include "ani_common_want.h" +#include "ani_remote_object.h" +#include "ani_utils.h" +#include "DriverExtensionContext_ani.h" +#include "hitrace_meter.h" +#include "hilog_wrapper.h" + +constexpr const char* DRIVER_EXTENSION_CLS = "L@ohos/app/ability/DriverExtensionAbility/DriverExtensionAbility;"; +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +AniDriverExtension::AniDriverExtension(STSRuntime& aniRuntime) : stsRuntime_(aniRuntime) {} +AniDriverExtension::~AniDriverExtension() = default; + +AniDriverExtension* AniDriverExtension::Create(const std::unique_ptr& runtime) +{ + return new AniDriverExtension(static_cast(*runtime)); +} + +void AniDriverExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + DriverExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { + HILOG_ERROR("DriverExtensionAbility Init abilityInfo error"); + return; + } + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + stsObj_ = stsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE, false, + abilityInfo_->srcEntrance); + if (stsObj_ == nullptr) { + HILOG_ERROR("Failed to get etsObj"); + return; + } + auto env = stsRuntime_.GetAniEnv(); + BindContext(env, record->GetWant(), application); + HILOG_DEBUG("%{public}s end.", __func__); +} + +void AniDriverExtension::BindContext(ani_env *env, std::shared_ptr want, + const std::shared_ptr &application) +{ + HILOG_DEBUG("StsServiceExtension BindContext Call"); + if (env == nullptr || want == nullptr) { + HILOG_ERROR("Want info is null or env is null"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + HILOG_ERROR("Failed to get context"); + return; + } + ani_object contextObj = CreateAniDriverExtensionContext(env, context, application); + if (contextObj == nullptr) { + HILOG_ERROR("null contextObj"); + return; + } + ani_field contextField; + ani_class cls = nullptr; + if ((env->FindClass(DRIVER_EXTENSION_CLS, &cls)) != ANI_OK) { + HILOG_ERROR("FindClass err: %{public}s", DRIVER_EXTENSION_CLS); + return; + } + auto status = env->Class_FindField(cls, "context", &contextField); + if (status != ANI_OK) { + HILOG_ERROR("Class_GetField context failed"); + return; + } + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(contextObj, &contextRef) != ANI_OK) { + HILOG_ERROR("GlobalReference_Create contextObj failed"); + return; + } + if (env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef) != ANI_OK) { + HILOG_ERROR("Object_SetField_Ref contextObj failed"); + return; + } + HILOG_DEBUG("BindContext end"); +} + +void AniDriverExtension::OnStart(const AAFwk::Want &want) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + Extension::OnStart(want); + auto env = stsRuntime_.GetAniEnv(); + ani_object ani_want = OHOS::AppExecFwk::WrapWant(env, want); + if (ANI_OK != env->Object_CallMethodByName_Void(stsObj_->aniObj, "onInit", nullptr, ani_want)) { + HILOG_ERROR("Failed to call the method: onInit"); + return; + } + HILOG_DEBUG("%{public}s end.", __func__); +} + +void AniDriverExtension::OnStop() +{ + HILOG_DEBUG("%{public}s begin.", __func__); + DriverExtension::OnStop(); + auto env = stsRuntime_.GetAniEnv(); + if (ANI_OK != env->Object_CallMethodByName_Void(stsObj_->aniObj, "onRelease", nullptr)) { + HILOG_ERROR("Failed to call the method: onRelease"); + return; + } + HILOG_DEBUG("%{public}s end.", __func__); +} + +sptr AniDriverExtension::OnConnect(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HILOG_DEBUG("%{public}s begin.", __func__); + Extension::OnConnect(want); + ani_ref result = nullptr; + auto env = stsRuntime_.GetAniEnv(); + ani_object ani_want = OHOS::AppExecFwk::WrapWant(env, want); + if (ANI_OK != env->Object_CallMethodByName_Ref(stsObj_->aniObj, "onConnect", nullptr, &result, ani_want)) { + HILOG_ERROR("Failed to call the method: onConnect"); + return nullptr; + } + if (result == nullptr) { + HILOG_ERROR("Failed to call onConnect : result == nullptr"); + return nullptr; + } + HILOG_DEBUG("%{public}s end.", __func__); + auto obj = reinterpret_cast(result); + auto remoteObj = AniGetNativeRemoteObject(env, obj); + if (remoteObj == nullptr) { + HILOG_ERROR("remoteObj null"); + return nullptr; + } + HILOG_DEBUG("end"); + return remoteObj; +} + +sptr AniDriverExtension::OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, bool &isAsyncCallback) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + if (callbackInfo == nullptr) { + HILOG_DEBUG("%{public}s is not AsyncCallback.", __func__); + isAsyncCallback = false; + return this->OnConnect(want); + } + Extension::OnConnect(want); + ani_boolean isAsync = false; + auto env = stsRuntime_.GetAniEnv(); + if (ANI_OK != env->Object_SetFieldByName_Long(stsObj_->aniObj, "connectCbInfo", + reinterpret_cast(callbackInfo))) { + HILOG_ERROR("Failed to Set the connectCbInfo"); + return nullptr; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + ani_ref result = nullptr; + if (ANI_OK != + env->Object_CallMethodByName_Ref(stsObj_->aniObj, "callOnConnect", nullptr, &result, wantRef)) { + HILOG_ERROR("2 Failed to call the method: callOnConnect"); + return nullptr; + } + auto obj = reinterpret_cast(result); + auto remoteObj = AniGetNativeRemoteObject(env, obj); + if (remoteObj == nullptr) { + HILOG_ERROR("remoteObj null"); + return nullptr; + } + if (ANI_OK != env->Object_GetFieldByName_Boolean(stsObj_->aniObj, "isOnConnectAsync", &isAsync)) { + HILOG_ERROR("Failed to Get the isOnConnectAsync"); + return nullptr; + } + if (isAsync) { + isAsyncCallback = true; + callbackInfo->Call(remoteObj); + AppExecFwk::AbilityTransactionCallbackInfo>::Destroy(callbackInfo); + return nullptr; + } + HILOG_DEBUG("%{public}s end.", __func__); + return remoteObj; +} + +void AniDriverExtension::OnDisconnect(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HILOG_DEBUG("%{public}s begin.", __func__); + Extension::OnDisconnect(want); + auto env = stsRuntime_.GetAniEnv(); + ani_object ani_want = OHOS::AppExecFwk::WrapWant(env, want); + if (ANI_OK != env->Object_CallMethodByName_Void(stsObj_->aniObj, "callOnDisConnect", nullptr, ani_want)) { + HILOG_ERROR("Failed to call the method: onDisconnect"); + return; + } + HILOG_DEBUG("%{public}s end.", __func__); +} + +void AniDriverExtension::OnDisconnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + if (callbackInfo == nullptr) { + this->OnDisconnect(want); + return; + } + auto env = stsRuntime_.GetAniEnv(); + Extension::OnDisconnect(want); + if (ANI_OK != env->Object_SetFieldByName_Long(stsObj_->aniObj, "disConnectCbInfo", + reinterpret_cast(callbackInfo))) { + HILOG_ERROR("Failed to Set the disConnectCbInfo"); + return; + } + ani_object ani_want = OHOS::AppExecFwk::WrapWant(env, want); + if (ANI_OK != env->Object_CallMethodByName_Void(stsObj_->aniObj, "callOnDisConnect", nullptr, ani_want)) { + HILOG_ERROR("Failed to call the method: callOnDisConnect"); + return; + } + ani_boolean isAsync = false; + if (ANI_OK != env->Object_GetFieldByName_Boolean(stsObj_->aniObj, "isOnDisconnectAsync", &isAsync)) { + HILOG_ERROR("Failed to Get the isOnDisconnectAsync"); + return; + } + if (isAsync) { + isAsyncCallback = true; + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); + return; + } + HILOG_DEBUG("%{public}s end.", __func__); +} + +ani_array_ref AniDriverExtension::ToAniStringList(ani_env *env, + const std::vector ¶ms, const uint32_t length) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + if (env == nullptr) { + return nullptr; + } + ani_array_ref result = nullptr; + ani_class stringCls = nullptr; + if (ANI_OK != env->FindClass("Lstd/core/String;", &stringCls)) { + HILOG_ERROR("FindClass Lstd/core/String Failed"); + return result; + } + if (env->Array_New_Ref(stringCls, length, nullptr, &result) != ANI_OK) { + return result; + } + for (auto i = 0; i < length; ++i) { + if (ANI_OK != env->Array_Set_Ref(result, i, AniStringUtils::ToAni(env, params[i]))) { + return result; + } + } + HILOG_DEBUG("%{public}s end.", __func__); + return result; +} + +void AniDriverExtension::Dump(const std::vector ¶ms, std::vector &info) +{ + HILOG_DEBUG("%{public}s begin.", __func__); + Extension::Dump(params, info); + auto env = stsRuntime_.GetAniEnv(); + ani_array_ref params_ = ToAniStringList(env, params, params.size()); + ani_ref result = nullptr; + if (ANI_OK != env->Object_CallMethodByName_Ref(stsObj_->aniObj, "onDump", nullptr, &result, params_)) { + HILOG_ERROR("Failed to call the method: Dump"); + return; + } + ani_double length; + if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast(result), "length", &length)) { + HILOG_ERROR("Object_GetPropertyByName_Double length Failed"); + return; + } + for (int i = 0; i < int(length); i++) { + ani_ref stringEntryRef; + if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast(result), "$_get", + "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i)) { + HILOG_ERROR("Object_CallMethodByName_Ref get Failed"); + return; + } + info.push_back(AniStringUtils::ToStd(env, static_cast(stringEntryRef))); + } + HILOG_DEBUG("%{public}s end.", __func__); +} +} // AbilityRuntime +} // OHOS \ No newline at end of file diff --git a/frameworks/js/taihe/driver_extension_context/BUILD.gn b/frameworks/js/taihe/driver_extension_context/BUILD.gn new file mode 100644 index 0000000..3795888 --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/BUILD.gn @@ -0,0 +1,109 @@ +# 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") + +copy_taihe_idl("copy_driverExtensionContext") { + sources = ["idl/DriverExtensionContext.taihe"] + #external_deps = [] +} + +subsystem_name = "hdf" +part_name = "external_device_manager" +taihe_application_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name/application" +native_path = "../../../../services/native" + +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [":copy_driverExtensionContext"] + outputs = [ + "$taihe_generated_file_path/src/DriverExtensionContext.ani.cpp", + "$taihe_generated_file_path/src/DriverExtensionContext.abi.c" + ] +} + +taihe_shared_library("DriverExtensionContext_native") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + include_dirs = [ + "include", + "$native_path/driver_extension/include", + ] + sources += [ + "src/ani_constructor.cpp", + "src/DriverExtensionContext.impl.cpp", + "$native_path/driver_extension/src/driver_extension_context.cpp", + ] + + deps = [ + ":run_taihe", + ] + + external_deps = [ + "ability_runtime:ability_connect_callback_stub", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "ability_runtime:ani_common", + "runtime_core:ani", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "ipc:ipc_napi", + "ipc:rpc_ani", + "bundle_framework:bms_ani_common", + ] +} + +generate_static_abc("driverExtensionContext_abc") { + base_url = "$taihe_application_file_path" + files = ["$taihe_generated_file_path/DriverExtensionContext.ets"] + is_boot_abc = "True" + device_dst_file = "/system/framework/driverExtensionContext_abc.abc" + dependencies = [":run_taihe"] +} + +ohos_prebuilt_etc("driverExtensionContext_etc") { + source = "$target_out_dir/driverExtensionContext_abc.abc" + module_install_dir = "framework" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps=[":driverExtensionContext_abc"] +} + +group("driverExtensionContext_taihe") { + deps = [ + ":driverExtensionContext_etc", + ":DriverExtensionContext_native", + ] + + #deps = [":run_taihe"] +} \ No newline at end of file diff --git a/frameworks/js/taihe/driver_extension_context/idl/DriverExtensionContext.taihe b/frameworks/js/taihe/driver_extension_context/idl/DriverExtensionContext.taihe new file mode 100644 index 0000000..4905b1e --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/idl/DriverExtensionContext.taihe @@ -0,0 +1,29 @@ +/* + * 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. + */ + +@!sts_inject_into_module("import ExtensionContext from 'application.ExtensionContext';") + +@!sts_inject(""" +export default class DriverExtensionContext extends ExtensionContext { + constructor() { + super(); + } + updateDriverState(): void { + this.UpdateDriverState(); + } + native UpdateDriverState(): void; + private nativePtr: long = 0; +} +""") \ No newline at end of file diff --git a/frameworks/js/taihe/driver_extension_context/include/DriverExtensionContext_ani.h b/frameworks/js/taihe/driver_extension_context/include/DriverExtensionContext_ani.h new file mode 100644 index 0000000..23d7192 --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/include/DriverExtensionContext_ani.h @@ -0,0 +1,33 @@ +/* + * 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_DRIVER_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ANI_DRIVER_EXTENSION_CONTEXT_H + +#include "ability_connect_callback.h" +#include "driver_extension_context.h" +#include "event_handler.h" +#include "js_free_install_observer.h" +#include "native_engine/native_engine.h" +#include "ohos_application.h" +#include + +namespace OHOS { +namespace AbilityRuntime { +ani_object CreateAniDriverExtensionContext(ani_env *env, std::shared_ptr context, + const std::shared_ptr &application); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_JS_DRIVER_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/js/taihe/driver_extension_context/include/ani_utils.h b/frameworks/js/taihe/driver_extension_context/include/ani_utils.h new file mode 100644 index 0000000..03cbc44 --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/include/ani_utils.h @@ -0,0 +1,310 @@ +/* + * 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...) + { + ani_object nullobj {}; + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + std::cerr << "[ANI] Not found namespace " << nsName << std::endl; + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + std::cerr << "[ANI] Not found for class " << clsName << std::endl; + return nullobj; + } + + std::cerr << "[ANI] AniObjectUtils Object_New_V " << clsName << std::endl; + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char *clsName, ...) + { + ani_object nullobj {}; + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + std::cerr << "[ANI] Not found for class " << clsName << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj {}; + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + std::cerr << "[ANI] Not found for class" << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + template + static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T *Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); // +1 for null terminator + char *utf8_buffer = buffer.data(); + + // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; + } + + static ani_string ToAni(ani_env *env, const std::string &str) + { + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + std::cerr << "[ANI] Unsupported ANI_VERSION_1" << std::endl; + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) {} + + bool IsInstanceOf(const std::string &cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template + bool IsInstanceOfType(); + + template + bool TryConvert(T &value); + + template + bool TryConvertArray(std::vector &value); + +private: + ani_env *env_; + ani_object obj_; +}; + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template <> +inline bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template <> +inline bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template <> +inline bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + return true; +} + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) {} + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template + std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template <> +inline std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast(aniValue); + return value; +} + +#endif diff --git a/frameworks/js/taihe/driver_extension_context/src/DriverExtensionContext.impl.cpp b/frameworks/js/taihe/driver_extension_context/src/DriverExtensionContext.impl.cpp new file mode 100644 index 0000000..5242598 --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/src/DriverExtensionContext.impl.cpp @@ -0,0 +1,88 @@ +/* + * 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 "DriverExtensionContext.impl.hpp" +#include "DriverExtensionContext.proj.hpp" +#include "stdexcept" +#include "taihe/runtime.hpp" + +#include "DriverExtensionContext_ani.h" +#include "ani_utils.h" +#include "ets_extension_context.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +constexpr const char *DRIVER_EXTENSION_CONTEXT_CLS = "Lapplication/DriverExtensionContext/DriverExtensionContext;"; +void UpdateDriverState([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + HILOG_DEBUG("UpdateDriverState begin"); + DriverExtensionContext *driverExtensionContext = AniObjectUtils::Unwrap(env, object); + if (driverExtensionContext == nullptr) { + return; + } + ErrCode innerErrorCode = driverExtensionContext->UpdateDriverState(); + if (innerErrorCode != ANI_OK) { + HILOG_ERROR("UpdateDriverState error"); + return; + } + HILOG_DEBUG("UpdateDriverState end"); +} + +ani_object CreateAniDriverExtensionContext(ani_env *env, std::shared_ptr context, + const std::shared_ptr &application) +{ + HILOG_DEBUG("CreateAniDriverExtensionContext begin"); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((env->FindClass(DRIVER_EXTENSION_CONTEXT_CLS, &cls)) != ANI_OK) { + HILOG_ERROR("FindClass err: %{public}s", DRIVER_EXTENSION_CONTEXT_CLS); + return nullptr; + } + ani_object contextObj = AniObjectUtils::Create(env, cls); + std::array methods = { + ani_native_function {"UpdateDriverState", nullptr, reinterpret_cast(UpdateDriverState)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + HILOG_ERROR("Cannot bind native methods to %{public}s", DRIVER_EXTENSION_CONTEXT_CLS); + return nullptr; + } + if (ANI_OK != AniObjectUtils::Wrap(env, contextObj, context.get())) { + HILOG_ERROR("Cannot wrap native object"); + return nullptr; + } + ani_field field = nullptr; + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + HILOG_ERROR("status: %{public}d", status); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + HILOG_ERROR("status: %{public}d", status); + return nullptr; + } + if (application == nullptr) { + HILOG_ERROR("application null"); + return nullptr; + } + OHOS::AbilityRuntime::CreatEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + HILOG_DEBUG("CreateAniDriverExtensionContext end"); + return contextObj; +} +} // namespace AbilityRuntime +} // namespace OHOS +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND diff --git a/frameworks/js/taihe/driver_extension_context/src/ani_constructor.cpp b/frameworks/js/taihe/driver_extension_context/src/ani_constructor.cpp new file mode 100644 index 0000000..947099e --- /dev/null +++ b/frameworks/js/taihe/driver_extension_context/src/ani_constructor.cpp @@ -0,0 +1,30 @@ +/* + * 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 "taihe/runtime.hpp" +#include "DriverExtensionContext.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != DriverExtensionContext::ANIRegister(env)) { + std::cerr << "Error from DriverExtensionContext::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/services/native/driver_extension/BUILD.gn b/services/native/driver_extension/BUILD.gn index 8dbeb10..cbb7295 100644 --- a/services/native/driver_extension/BUILD.gn +++ b/services/native/driver_extension/BUILD.gn @@ -13,6 +13,7 @@ import("//build/ohos.gni") +js_path = "../../../frameworks/js" config("ability_config") { visibility = [ ":*" ] cflags = [] @@ -22,15 +23,23 @@ config("ability_config") { } ohos_shared_library("driver_extension") { - include_dirs = [ "include" ] + include_dirs = [ + "include", + "$js_path/ani/driver_extension_ability/native/include", + "$js_path/taihe/driver_extension_context/include" + ] sources = [ "src/driver_extension.cpp", "src/driver_extension_context.cpp", "src/js_driver_extension.cpp", "src/js_driver_extension_context.cpp", + "$js_path/ani/driver_extension_ability/native/src/ani_driver_extension.cpp" ] + deps = [ + "$js_path/taihe/driver_extension_context:DriverExtensionContext_native" + ] external_deps = [ "ability_base:want", "ability_runtime:ability_connect_callback_stub", @@ -40,6 +49,7 @@ ohos_shared_library("driver_extension") { "ability_runtime:app_context", "ability_runtime:extensionkit_native", "ability_runtime:napi_common", + "ability_runtime:ani_common", "ability_runtime:runtime", "c_utils:utils", "eventhandler:libeventhandler", @@ -48,6 +58,8 @@ ohos_shared_library("driver_extension") { "ipc:ipc_core", "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", + "ipc:rpc_ani", ] cflags_cc = [ "-fno-asynchronous-unwind-tables", diff --git a/services/native/driver_extension/src/driver_extension.cpp b/services/native/driver_extension/src/driver_extension.cpp index a14bc12..50e629d 100644 --- a/services/native/driver_extension/src/driver_extension.cpp +++ b/services/native/driver_extension/src/driver_extension.cpp @@ -15,6 +15,7 @@ #include "driver_extension.h" +#include "ani_driver_extension.h" #include "configuration_utils.h" #include "connection_manager.h" #include "hilog_wrapper.h" @@ -46,7 +47,8 @@ DriverExtension* DriverExtension::Create(const std::unique_ptr& runtime switch (runtime->GetLanguage()) { case Runtime::Language::JS: return JsDriverExtension::Create(runtime); - + case Runtime::Language::STS: + return AniDriverExtension::Create(runtime); default: return new DriverExtension(); } -- Gitee