diff --git a/frameworks/ets/ani/ability_manager/BUILD.gn b/frameworks/ets/ani/ability_manager/BUILD.gn index fedaa89c1c00b27b8891e796b271b8f18e6ce01c..b345a9706cae3a98eec5c506496a523275f0298c 100644 --- a/frameworks/ets/ani/ability_manager/BUILD.gn +++ b/frameworks/ets/ani/ability_manager/BUILD.gn @@ -32,6 +32,7 @@ ohos_shared_library("ability_ability_manager_ani_kit") { "${ability_runtime_path}/interfaces/inner_api/runtime/include", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", ] @@ -41,8 +42,8 @@ ohos_shared_library("ability_ability_manager_ani_kit") { sources = [ "./src/sts_ability_manager.cpp", - "./src/sts_ability_manager_utils.cpp", - ] + "./src/ets_ability_foreground_state_observer.cpp", + "./src/sts_ability_manager_utils.cpp",] cflags = [] if (target_cpu == "arm") { diff --git a/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h b/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..6073510705f21a99f215e750ccb45bcac6e7dcfd --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h @@ -0,0 +1,58 @@ +/* + * 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_ETS_ABILITY_FOREGROUND_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_FOREGROUND_STATE_OBSERVER_H + +#include + +#include "ability_foreground_state_observer_stub.h" +#include "ability_state_data.h" +#include "event_handler.h" +#include "sts_runtime.h" +#include "ani_common_util.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +using OHOS::AppExecFwk::AbilityForegroundStateObserverStub; +using OHOS::AppExecFwk::AbilityStateData; +class ETSAbilityForegroundStateObserver : public AbilityForegroundStateObserverStub { +public: + explicit ETSAbilityForegroundStateObserver(ani_vm *etsVm); + virtual ~ETSAbilityForegroundStateObserver() = default; + + void OnAbilityStateChanged(const AbilityStateData &abilityStateData); + void HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData); + void AddEtsObserverObject(ani_env *env, ani_object etsObserverObject); + bool RemoveEtsObserverObject(const ani_object &observerObj); + STSNativeReference GetObserverObject(const ani_object &observerObject); + void RemoveAllEtsObserverObject(); + bool IsEmpty(); + void SetValid(bool valid); + void CallStsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...); + inline size_t GetEtsObserverMapSize() { return etsObserverObjects_.size(); } +private: + void ReleaseObjectRefrence(ani_ref etsObjRef); + +private: + ani_vm *etsVm_; + volatile bool valid_ = true; + std::vector etsObserverObjects_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_FOREGROUND_STATE_OBSERVER_H diff --git a/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h b/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h index a04a51bd1bdc6d721db514df29284f2116930a1f..c08948aadd7357def3af7f410b45e489b0ae49ed 100644 --- a/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h +++ b/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h @@ -22,16 +22,6 @@ namespace OHOS { namespace AbilityManagerSts { void StsAbilityManagerRegistryInit(ani_env *env); - -class StsAbilityManager final { -public: - static StsAbilityManager &GetInstance() - { - static StsAbilityManager instance; - return instance; - } - static void GetAbilityRunningInfos(ani_env *env, ani_object callback); -}; } // namespace AbilityManagerSts } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_H diff --git a/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h b/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h index 3b35d3397c3c60040acd3be562abc843d7e0c0dd..06630e46d259fd0bdfd1851d710214097058a9c8 100644 --- a/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h +++ b/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h @@ -17,10 +17,14 @@ #define OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_UTILS_H #include "ability_running_info.h" +#include "ability_state_data.h" #include "sts_runtime.h" namespace OHOS { namespace AbilityManagerSts { +using OHOS::AppExecFwk::AbilityStateData; +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &abilityStateData); +bool SetAbilityStateData(ani_env *env, ani_object object, const AbilityStateData &abilityStateData); bool WrapAbilityRunningInfo(ani_env *env, ani_object &infoObj, const AAFwk::AbilityRunningInfo &info); bool WrapAbilityRunningInfoArray( ani_env *env, ani_object &arrayObj, const std::vector &infos); diff --git a/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp b/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..389c5ec27e97e1549668b80996cfbaf1ff1bb2ab --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp @@ -0,0 +1,191 @@ +/* + * 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 "ets_ability_foreground_state_observer.h" +#include "sts_ability_manager_utils.h" +#include "hilog_tag_wrapper.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ABILITY_FOREGROUND_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AbilityForegroundStateObserver/AbilityForegroundStateObserver;"; +constexpr const char *SIGNATURE_ABILITY_STATE_DATA = "Lapplication/AbilityStateData/AbilityStateData;:V"; +} +ETSAbilityForegroundStateObserver::ETSAbilityForegroundStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +void ETSAbilityForegroundStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "OnAbilityStateChanged called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid appms"); + return; + } + HandleOnAbilityStateChanged(abilityStateData); +} + +void ETSAbilityForegroundStateObserver::CallStsFunction(ani_env* env, ani_object stsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(ABILITY_FOREGROUND_STATE_OBSERVER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find observer failed status : %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::ABILITYMGR, "end"); + return; +} + +void ETSAbilityForegroundStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleOnAbilityStateChanged called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "etsVm_ nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "env nullptr"); + return; + } + for (auto &item : etsObserverObjects_) { + auto abilityStateDataObj = AbilityManagerSts::WrapAbilityStateData(env, abilityStateData); + if (abilityStateDataObj != nullptr && item.aniRef != nullptr) { + CallStsFunction(env, reinterpret_cast(item.aniRef), + "onAbilityStateChanged", SIGNATURE_ABILITY_STATE_DATA, abilityStateDataObj); + } + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleOnAbilityStateChanged end"); +} + +void ETSAbilityForegroundStateObserver::AddEtsObserverObject(ani_env *env, ani_object etsObserverObject) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "AddEtsObserverObject called"); + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + return; + } + if (GetObserverObject(etsObserverObject).aniObj != nullptr) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "observer exist"); + return; + } + ani_ref global = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(etsObserverObject, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return; + } + STSNativeReference stRef; + stRef.aniObj = etsObserverObject; + stRef.aniRef = global; + etsObserverObjects_.emplace_back(stRef); + TAG_LOGD(AAFwkTag::ABILITYMGR, "AddEtsObserverObject end"); +} + +STSNativeReference ETSAbilityForegroundStateObserver::GetObserverObject(const ani_object &observerObject) +{ + if (observerObject == nullptr) { + return STSNativeReference(); + } + for (const auto& observer : etsObserverObjects_) { + if (observer.aniObj == observerObject) { + return observer; + } + } + return STSNativeReference(); +} + +void ETSAbilityForegroundStateObserver::ReleaseObjectRefrence(ani_ref etsObjRef) +{ + if (etsObjRef == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null etsObj"); + return; + } + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null etsVm_"); + return; + } + ani_env *env = nullptr; + ani_status status = etsVm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetEnv failed status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Delete(etsObjRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GlobalReference_Delete failed status = %{public}d", status); + return; + } +} + +bool ETSAbilityForegroundStateObserver::RemoveEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + return false; + } + auto etsNativeRefrence = GetObserverObject(observerObj); + if (etsNativeRefrence.aniObj != nullptr) { + etsObserverObjects_.emplace_back(etsNativeRefrence); + ReleaseObjectRefrence(etsNativeRefrence.aniRef); + } + return true; +} + +void ETSAbilityForegroundStateObserver::RemoveAllEtsObserverObject() +{ + auto itr = etsObserverObjects_.begin(); + for (; itr != etsObserverObjects_.end(); ++itr) { + ReleaseObjectRefrence(itr->aniRef); + itr = etsObserverObjects_.erase(itr); + } +} + +void ETSAbilityForegroundStateObserver::SetValid(const bool valid) +{ + valid_ = valid; +} + +bool ETSAbilityForegroundStateObserver::IsEmpty() +{ + return etsObserverObjects_.empty(); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp b/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp index 7759ce7b8ef6e8600c38c21d84da825c23055893..9035666958e9b6ec524294f5a1a4721139477bf0 100644 --- a/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp +++ b/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp @@ -28,88 +28,213 @@ #include "sts_ability_manager_utils.h" #include "sts_error_utils.h" #include "system_ability_definition.h" +#include "ets_ability_foreground_state_observer.h" +#include "app_mgr_constants.h" +#include "app_mgr_interface.h" namespace OHOS { namespace AbilityManagerSts { constexpr int32_t ERR_FAILURE = -1; -sptr GetAbilityManagerInstance() -{ - sptr systemAbilityManager = - SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - sptr abilityManagerObj = - systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); - return iface_cast(abilityManagerObj); -} - -static ani_object GetForegroundUIAbilities(ani_env *env) -{ - TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilities"); - - if (env == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); - return nullptr; +class EtsAbilityManager final { +private: + static sptr observerForeground_; +public: + static sptr GetAbilityManagerInstance() + { + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr abilityManagerObj = + systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + return iface_cast(abilityManagerObj); } - sptr abilityManager = GetAbilityManagerInstance(); - if (abilityManager == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityManager is null"); - AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); - return nullptr; - } - std::vector list; - int32_t ret = abilityManager->GetForegroundUIAbilities(list); - if (ret != ERR_OK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "failed: ret=%{public}d", ret); - AbilityRuntime::AbilityErrorCode code = AbilityRuntime::GetJsErrorCodeByNativeError(ret); - AbilityRuntime::ThrowStsError(env, code); - return nullptr; + static OHOS::sptr GetAppManagerInstance() + { + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr appObject = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID); + return OHOS::iface_cast(appObject); } - TAG_LOGD(AAFwkTag::ABILITYMGR, "GetForegroundUIAbilities succeeds, list.size=%{public}zu", list.size()); - ani_object aniArray = AppExecFwk::CreateAniAbilityStateDataArray(env, list); - if (aniArray == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "null aniArray"); - AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); - return nullptr; + + static ani_object GetForegroundUIAbilities(ani_env *env) + { + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilities"); + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + sptr abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityManager is null"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + std::vector list; + int32_t ret = abilityManager->GetForegroundUIAbilities(list); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "failed: ret=%{public}d", ret); + AbilityRuntime::AbilityErrorCode code = AbilityRuntime::GetJsErrorCodeByNativeError(ret); + AbilityRuntime::ThrowStsError(env, code); + return nullptr; + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetForegroundUIAbilities succeeds, list.size=%{public}zu", list.size()); + ani_object aniArray = AppExecFwk::CreateAniAbilityStateDataArray(env, list); + if (aniArray == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null aniArray"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + return aniArray; } - return aniArray; -} -static void GetTopAbility(ani_env *env, ani_object callback) -{ - TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetTopAbility"); - if (env == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + static void GetTopAbility(ani_env *env, ani_object callback) + { + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetTopAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + #ifdef ENABLE_ERRCODE + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + #endif + AppExecFwk::ElementName elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); + int resultCode = 0; + ani_object elementNameobj = AppExecFwk::WrapElementName(env, elementName); + if (elementNameobj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null elementNameobj"); + resultCode = ERR_FAILURE; + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Create Gloabl ref for abilitymanager failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + elementNameobj); return; } -#ifdef ENABLE_ERRCODE - auto selfToken = IPCSkeleton::GetSelfTokenID(); - if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); - AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); - return; + + static void GetAbilityRunningInfos(ani_env *env, ani_object callback) + { + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetAbilityRunningInfos"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + std::vector infos; + auto errcode = AAFwk::AbilityManagerClient::GetInstance()->GetAbilityRunningInfos(infos); + ani_object retObject = nullptr; + WrapAbilityRunningInfoArray(env, retObject, infos); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, errcode), retObject); } -#endif - AppExecFwk::ElementName elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); - int resultCode = 0; - ani_object elementNameobj = AppExecFwk::WrapElementName(env, elementName); - if (elementNameobj == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "null elementNameobj"); - resultCode = ERR_FAILURE; + + static void nativeOn(ani_env *env, ani_string aniType, ani_object aniObserver) + { + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOn called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "env null ptr"); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, aniType, strType)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AbilityForegroundStateObserver."); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return; + } + if (observerForeground_ == nullptr) { + observerForeground_ = new (std::nothrow) OHOS::AbilityRuntime::ETSAbilityForegroundStateObserver(aniVM); + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observerForeground_"); + OHOS::AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + } + if (observerForeground_->IsEmpty()) { + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appManager null ptr"); + OHOS::AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + int32_t ret = appManager->RegisterAbilityForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::ABILITYMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::ThrowStsErrorByNativeErr(env, static_cast(ret)); + return; + } + } + observerForeground_->AddEtsObserverObject(env, aniObserver); + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOn end"); } - ani_ref callbackRef = nullptr; - auto status = env->GlobalReference_Create(callback, &callbackRef); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "Create Gloabl ref for abilitymanager failed %{public}d", status); - AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); - return; + + static void nativeOff(ani_env *env, ani_string aniType, ani_object aniObserver) + { + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOff called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "env null ptr"); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, aniType, strType)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AbilityForegroundStateObserver."); + return; + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniObserver, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined) { + observerForeground_->RemoveEtsObserverObject(aniObserver); + } else { + observerForeground_->RemoveAllEtsObserverObject(); + } + if (observerForeground_->IsEmpty()) { + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appManager null ptr"); + OHOS::AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + int32_t ret = appManager->UnregisterAbilityForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::ABILITYMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::ThrowStsErrorByNativeErr(env, static_cast(ret)); + } + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOff end"); } - AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), - elementNameobj); - return; -} +}; + +sptr EtsAbilityManager::observerForeground_ = nullptr; void StsAbilityManagerRegistryInit(ani_env *env) { @@ -132,11 +257,16 @@ void StsAbilityManagerRegistryInit(ani_env *env) ani_native_function { "nativeGetForegroundUIAbilities", ":Lescompat/Array;", - reinterpret_cast(GetForegroundUIAbilities) + reinterpret_cast(EtsAbilityManager::GetForegroundUIAbilities) }, - ani_native_function {"nativeGetTopAbility", nullptr, reinterpret_cast(GetTopAbility)}, + ani_native_function {"nativeGetTopAbility", nullptr, + reinterpret_cast(EtsAbilityManager::GetTopAbility)}, ani_native_function { "nativeGetAbilityRunningInfos", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", - reinterpret_cast(StsAbilityManager::GetAbilityRunningInfos) }, + reinterpret_cast(EtsAbilityManager::GetAbilityRunningInfos) }, + ani_native_function { "nativeOn", nullptr, + reinterpret_cast(EtsAbilityManager::nativeOn) }, + ani_native_function { "nativeOff", nullptr, + reinterpret_cast(EtsAbilityManager::nativeOff) } }; status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); if (status != ANI_OK) { @@ -155,7 +285,6 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) TAG_LOGE(AAFwkTag::ABILITYMGR, "null vm or result"); return ANI_INVALID_ARGS; } - ani_env *env = nullptr; ani_status status = ANI_ERROR; status = vm->GetEnv(ANI_VERSION_1, &env); @@ -169,19 +298,5 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) return ANI_OK; } } - -void StsAbilityManager::GetAbilityRunningInfos(ani_env *env, ani_object callback) -{ - TAG_LOGD(AAFwkTag::ABILITYMGR, "GetAbilityRunningInfos"); - if (env == nullptr) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); - return; - } - std::vector infos; - auto errcode = AAFwk::AbilityManagerClient::GetInstance()->GetAbilityRunningInfos(infos); - ani_object retObject = nullptr; - WrapAbilityRunningInfoArray(env, retObject, infos); - AppExecFwk::AsyncCallback(env, callback, OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, errcode), retObject); -} } // namespace AbilityManagerSts } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp b/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp index 787bc3706a81fc59a4ab42cc2443e7219e3425ff..075aff7e2973991a8d61eaa7b50768daed00268b 100644 --- a/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp +++ b/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp @@ -14,7 +14,9 @@ */ #include "sts_ability_manager_utils.h" - +#include +#include "ability_state.h" +#include "hilog_tag_wrapper.h" #include "ani_common_util.h" #include "ani_common_want.h" #include "ani_enum_convert.h" @@ -151,5 +153,95 @@ bool WrapAbilityRunningInfoInner( } return true; } + +bool SetAbilityStateData(ani_env *env, ani_object object, const AbilityStateData &abilityStateData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + if ((status = env->Object_SetFieldByName_Ref(object, "moduleName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.moduleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "moduleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.bundleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "bundleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "abilityName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.abilityName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "pid", static_cast(abilityStateData.pid))) + != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "pid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "uid", abilityStateData.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "uid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "state", abilityStateData.abilityState)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "state failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "abilityType", abilityStateData.abilityType)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityType failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Boolean(object, "isAtomicService", + abilityStateData.isAtomicService)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "isAtomicService failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "appCloneIndex", + OHOS::AppExecFwk::createInt(env, abilityStateData.appCloneIndex))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appCloneIndex failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &abilityStateData) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass("Lapplication/AbilityStateData/AbilityStateData;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "find class failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New AppStateData failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null object"); + return nullptr; + } + if (!SetAbilityStateData(env, object, abilityStateData)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppStateData failed"); + return nullptr; + } + return object; +} + } // namespace AbilityManagerSts } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets index 274a24fc0af837e4077fcee9f2a9c1d7ccb4765b..981d13c3febb4486169af5cde21e0b719d2c8a95 100644 --- a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets +++ b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets @@ -100,6 +100,17 @@ export function getTopAbility(callback: AsyncCallback): void }); } +export native function nativeOn(type:string, observer: AbilityForegroundStateObserver): void; +function on(type: 'abilityForegroundState', observer: AbilityForegroundStateObserver): void +{ + nativeOn('abilityForegroundState', observer); +} + +export native function nativeOff(type:string, observer?: AbilityForegroundStateObserver): void; +function off(type: 'abilityForegroundState', observer?: AbilityForegroundStateObserver): void { + nativeOff('abilityForegroundState', observer); +} + export enum AbilityState { INITIAL = 0, FOCUS = 2, diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index cf3a702bf832c0ccaefec72c9b95e6601fab2ebf..f7792fa05f5db372136f76be3e13a718d4d5130f 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -771,6 +771,23 @@ ohos_prebuilt_etc("ability_delegator_application_testRunner_abc_etc") { deps = [ ":ability_delegator_application_testRunner_abc" ] } +generate_static_abc("ability_foreground_state_observer_abc") { + base_url = "." + files = [ "./application/AbilityForegroundStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_foreground_state_observer_abc.abc" +} + +ohos_prebuilt_etc("ability_foreground_state_observer_abc_etc") { + source = "$target_out_dir/ability_foreground_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_foreground_state_observer_abc" ] +} + generate_static_abc("ability_runtime_OpenLink_Options_abc") { base_url = "./" files = [ "./@ohos.app.ability.OpenLinkOptions.ets" ] @@ -892,6 +909,7 @@ group("ets_packages") { ":ability_delegator_application_testRunner_abc_etc", ":ability_delegator_args_abc_etc", ":ability_delegator_registry_abc_etc", + ":ability_foreground_state_observer_abc_etc", ":ability_runtime_abilityResult_abc_etc", ":ability_runtime_ability_callee_abc_etc", ":ability_runtime_ability_caller_abc_etc", diff --git a/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets b/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets new file mode 100644 index 0000000000000000000000000000000000000000..c5652df4a321cbecbba23f5499593ad53856240c --- /dev/null +++ b/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets @@ -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 AbilityStateData from 'application.AbilityStateData'; + +class AbilityForegroundStateObserver { + onAbilityStateChanged(abilityStateData: AbilityStateData): void {} +} + +export default AbilityForegroundStateObserver; \ No newline at end of file