From e8327187dcffc1528c4281dae5189fd5d8d47a5c Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Sat, 7 Jun 2025 21:00:28 +0800 Subject: [PATCH] appManager AbilityFirstFrameStateObserver AppForegroundStateObserver Signed-off-by: zhangzezhong --- frameworks/ets/ani/app_manager/BUILD.gn | 2 + .../ets_ability_first_frame_state_observer.h | 77 +++++ .../ets_app_foreground_state_observer.h | 55 ++++ .../include/sts_app_manager_utils.h | 10 + ...ets_ability_first_frame_state_observer.cpp | 224 ++++++++++++++ .../src/ets_app_foreground_state_observer.cpp | 164 ++++++++++ .../ani/app_manager/src/sts_app_manager.cpp | 253 +++++++++++++++- .../app_manager/src/sts_app_manager_utils.cpp | 76 +++++ .../src/sts_app_state_observer.cpp | 284 ++++++++++++++++++ .../ets/ets/@ohos.app.ability.appManager.ets | 26 ++ frameworks/ets/ets/BUILD.gn | 51 ++++ .../AbilityFirstFrameStateData.ets | 30 ++ .../AbilityFirstFrameStateObserver.ets | 24 ++ .../AbilityForegroundStateObserver.ets | 21 ++ .../AppForegroundStateObserver.ets | 20 ++ 15 files changed, 1314 insertions(+), 3 deletions(-) create mode 100644 frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h create mode 100644 frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h create mode 100644 frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp create mode 100644 frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp create mode 100644 frameworks/ets/ani/app_manager/src/sts_app_state_observer.cpp create mode 100644 frameworks/ets/ets/application/AbilityFirstFrameStateData.ets create mode 100644 frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets create mode 100644 frameworks/ets/ets/application/AbilityForegroundStateObserver.ets create mode 100644 frameworks/ets/ets/application/AppForegroundStateObserver.ets diff --git a/frameworks/ets/ani/app_manager/BUILD.gn b/frameworks/ets/ani/app_manager/BUILD.gn index 0e46637799e..ad599d3ea57 100644 --- a/frameworks/ets/ani/app_manager/BUILD.gn +++ b/frameworks/ets/ani/app_manager/BUILD.gn @@ -39,6 +39,8 @@ ohos_shared_library("ability_app_manager_ani_kit") { public_configs = [] sources = [ + "./src/ets_ability_first_frame_state_observer.cpp", + "./src/ets_app_foreground_state_observer.cpp", "./src/sts_app_manager.cpp", "./src/sts_app_manager_utils.cpp", ] diff --git a/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h b/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h new file mode 100644 index 00000000000..aa7c2a076a1 --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 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_FIRST_FRAME_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_FIRST_FRAME_STATE_OBSERVER_H + +#ifdef SUPPORT_GRAPHICS +#include +#include + +#include "ability_first_frame_state_observer_stub.h" +#include "ability_manager_interface.h" +#include "singleton.h" +#include "event_handler.h" +#include "ability_first_frame_state_data.h" +#include "sts_runtime.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { +using OHOS::AppExecFwk::AbilityFirstFrameStateObserverStub; +using OHOS::AppExecFwk::AbilityFirstFrameStateData; +class ETSAbilityFirstFrameStateObserver : public AbilityFirstFrameStateObserverStub { +public: + explicit ETSAbilityFirstFrameStateObserver(ani_vm *vm); + virtual ~ETSAbilityFirstFrameStateObserver() = default; + void OnAbilityFirstFrameState(const AbilityFirstFrameStateData &abilityFirstFrameStateData) override; + void HandleOnAbilityFirstFrameState(const AbilityFirstFrameStateData &abilityFirstFrameStateData); + void CallStsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...); + void SetEtsObserverObject(const ani_object &etsObserverObject); + void ResetEtsObserverObject(); + std::shared_ptr GetAniObserver() { return etsObserverObject_;} + +private: + ani_vm *etsVm_; + std::shared_ptr etsObserverObject_; +}; + +class ETSAbilityFirstFrameStateObserverManager { +public: + static ETSAbilityFirstFrameStateObserverManager *GetInstance() + { + static ETSAbilityFirstFrameStateObserverManager instance; + return &instance; + } + ~ETSAbilityFirstFrameStateObserverManager() = default; + void AddEtsAbilityFirstFrameStateObserver(const sptr observer); + bool IsObserverObjectExist(const ani_object &esObserverObject); + void RemoveAllEtsObserverObjects(sptr &abilityManager); + void RemoveEtsObserverObject(sptr &abilityManager, + const ani_object &etsObserverObject); +private: + ETSAbilityFirstFrameStateObserverManager() = default; + DISALLOW_COPY_AND_MOVE(ETSAbilityFirstFrameStateObserverManager); + std::shared_ptr GetObserverObject(const ani_object &etsObserverObject); + +private: + std::mutex observerListLock_; + std::list> etsAbilityFirstFrameStateObserverList_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // SUPPORT_GRAPHICS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_FIRST_FRAME_STATE_OBSERVER_H diff --git a/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h b/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h new file mode 100644 index 00000000000..b71d66d196d --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 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_APP_FOREGROUND_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_FOREGROUND_STATE_OBSERVER_H + +#include +#include + +#include "app_foreground_state_observer_stub.h" +#include "event_handler.h" +#include "sts_runtime.h" +#include "ani_common_util.h" +#include "event_handler.h" + +namespace OHOS { +namespace AbilityRuntime { +using OHOS::AppExecFwk::AppForegroundStateObserverStub; +using OHOS::AppExecFwk::AppStateData; +class ETSAppForegroundStateObserver : public AppForegroundStateObserverStub { +public: +virtual ~ETSAppForegroundStateObserver() = default; +explicit ETSAppForegroundStateObserver(ani_vm *etsVm); + void OnAppStateChanged(const AppStateData &appStateData); + void HandleOnAppStateChanged(const AppStateData &appStateData); + void AddEtsObserverObject(const ani_object &observerObj); + void RemoveEtsObserverObject(const ani_object &observerObj); + void RemoveAllEtsObserverObjects(); + std::shared_ptr GetObserverObject(const ani_object &observerObject); + void CallStsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...); + bool IsEmpty(); + void SetValid(bool valid); + +private: + ani_vm *etsVm_; + volatile bool valid_ = true; + std::set> etsObserverObjectSet_; + std::mutex etsObserverObjectSetLock_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APP_FOREGROUND_STATE_OBSERVER_H diff --git a/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h b/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h index a3af678cbdd..b9f5ee47656 100644 --- a/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h +++ b/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h @@ -22,6 +22,10 @@ #include "running_multi_info.h" #include "process_data.h" #include "keep_alive_info.h" +#include "ability_state_data.h" +#ifdef SUPPORT_GRAPHICS +#include "ability_first_frame_state_data.h" +#endif namespace OHOS { namespace AppManagerSts { @@ -53,6 +57,12 @@ bool UnWrapArrayDouble(ani_env *env, ani_object arrayObj, std::vector & ani_object CreateKeepAliveInfoArray(ani_env *env, const std::vector &infos); ani_object WrapKeepAliveInfo(ani_env *env, const AbilityRuntime::KeepAliveInfo &keepAliveInfo); bool SetKeepAliveInfo(ani_env *env, ani_object object, const AbilityRuntime::KeepAliveInfo &keepInfo); +#ifdef SUPPORT_GRAPHICS +ani_object WrapAbilityFirstFrameStateData(ani_env *env, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData); +bool SetAbilityFirstFrameStateData(ani_env *env, ani_object object, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData); +#endif } // namespace AppManagerSts } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_UTILS_H diff --git a/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp b/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp new file mode 100644 index 00000000000..2c06fbae3c8 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifdef SUPPORT_GRAPHICS +#include "ets_ability_first_frame_state_observer.h" +#include "hilog_tag_wrapper.h" +#include "sts_app_manager_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ABILITY_FIRST_FRAME_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;"; +} +ETSAbilityFirstFrameStateObserver::ETSAbilityFirstFrameStateObserver(ani_vm *vm) : etsVm_(vm) {} + +void ETSAbilityFirstFrameStateObserver::OnAbilityFirstFrameState( + const AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnAbilityFirstFrameState called"); + HandleOnAbilityFirstFrameState(abilityFirstFrameStateData); + TAG_LOGD(AAFwkTag::APPMGR, "OnAbilityFirstFrameState end"); +} + +void ETSAbilityFirstFrameStateObserver::HandleOnAbilityFirstFrameState( + const AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "HandleOnAbilityFirstFrameState called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "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::APPMGR, "status : %{public}d", status); + return; + } + auto paramObj = AppManagerSts::WrapAbilityFirstFrameStateData(env, abilityFirstFrameStateData); + if (paramObj != nullptr && etsObserverObject_ != nullptr) { + CallStsFunction(env, *etsObserverObject_, "onAbilityFirstFrameDrawn", nullptr, paramObj); + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } +} + +void ETSAbilityFirstFrameStateObserver::CallStsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(ABILITY_FIRST_FRAME_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::APPMGR, "status: %{public}d", status); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::APPMGR, "end"); + return; +} + +void ETSAbilityFirstFrameStateObserver::SetEtsObserverObject(const ani_object &etsObserverObject) +{ + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + ani_env *env = nullptr; + ani_status status = etsVm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return; + } + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + ani_ref observerRef = nullptr; + if ((status = env->GlobalReference_Create(etsObserverObject, &observerRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + etsObserverObject_ = std::make_shared(etsObserverObject); +} + +void ETSAbilityFirstFrameStateObserver::ResetEtsObserverObject() +{ + if (etsObserverObject_) { + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + ani_env *env = nullptr; + ani_status status = etsVm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Delete(*etsObserverObject_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GlobalReference_Delete failed status = %{public}d", status); + return; + } + etsObserverObject_.reset(); + } +} + +void ETSAbilityFirstFrameStateObserverManager::AddEtsAbilityFirstFrameStateObserver( + const sptr observer) +{ + if (observer == nullptr || observer->GetAniObserver() == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + std::lock_guard lock(observerListLock_); + etsAbilityFirstFrameStateObserverList_.emplace_back(observer); +} + +bool ETSAbilityFirstFrameStateObserverManager::IsObserverObjectExist(const ani_object &esObserverObject) +{ + if (GetObserverObject(esObserverObject) == nullptr) { + TAG_LOGD(AAFwkTag::APPMGR, "observer not exist"); + return false; + } + TAG_LOGD(AAFwkTag::APPMGR, "observer exist"); + return true; +} + +void ETSAbilityFirstFrameStateObserverManager::RemoveAllEtsObserverObjects( + sptr &abilityManager) +{ + TAG_LOGD(AAFwkTag::APPMGR, "RemoveAllEtsObserverObject called"); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr"); + return; + } + std::lock_guard lock(observerListLock_); + for (auto observer : etsAbilityFirstFrameStateObserverList_) { + abilityManager->UnregisterAbilityFirstFrameStateObserver(observer); + observer->ResetEtsObserverObject(); + } + etsAbilityFirstFrameStateObserverList_.clear(); +} + +void ETSAbilityFirstFrameStateObserverManager::RemoveEtsObserverObject( + sptr &abilityManager, const ani_object &etsObserverObject) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr"); + return; + } + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + auto it = etsAbilityFirstFrameStateObserverList_.begin(); + for (; it != etsAbilityFirstFrameStateObserverList_.end(); ++it) { + if (*it == nullptr) { + continue; + } + std::shared_ptr tmpObject = (*it)->GetAniObserver(); + if (tmpObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null value"); + continue; + } + if (*tmpObject == etsObserverObject) { + abilityManager->UnregisterAbilityFirstFrameStateObserver(*it); + (*it)->ResetEtsObserverObject(); + etsAbilityFirstFrameStateObserverList_.erase(it); + return; + } + } +} + +std::shared_ptr ETSAbilityFirstFrameStateObserverManager::GetObserverObject( + const ani_object &etsObserverObject) +{ + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return nullptr; + } + std::lock_guard lock(observerListLock_); + for (auto &observer : etsAbilityFirstFrameStateObserverList_) { + if (observer == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + continue; + } + std::shared_ptr tmpObject = observer->GetAniObserver(); + if (tmpObject && *tmpObject == etsObserverObject) { + return tmpObject; + } + } + return nullptr; +} +} // namespace AbilityRuntime +} // namespace OHOS +#endif // SUPPORT_GRAPHICS \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp b/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp new file mode 100644 index 00000000000..2e958041f3b --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2023-2024 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_app_foreground_state_observer.h" +#include "hilog_tag_wrapper.h" +#include "sts_app_manager_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* APP_FOREGROUND_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;"; +} +ETSAppForegroundStateObserver::ETSAppForegroundStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +void ETSAppForegroundStateObserver::OnAppStateChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnAppStateChanged called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "invalid appMgr"); + return; + } + HandleOnAppStateChanged(appStateData); +} + +void ETSAppForegroundStateObserver::HandleOnAppStateChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "HandleOnAppStateChanged 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::ABILITYMGR, "status : %{public}d", status); + return; + } + std::lock_guard lock(etsObserverObjectSetLock_); + for (auto &item : etsObserverObjectSet_) { + auto appStateDataObj = AppManagerSts::WrapAppStateData(env, appStateData); + if (appStateDataObj != nullptr) { + CallStsFunction(env, *item, "onAppStateChanged", nullptr, appStateDataObj); + } + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + } +} + +void ETSAppForegroundStateObserver::CallStsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(APP_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(etsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::APPMGR, "end"); + return; +} + +void ETSAppForegroundStateObserver::AddEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + ani_env *env = nullptr; + ani_status status = etsVm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return; + } + if (GetObserverObject(observerObj) == nullptr) { + std::lock_guard lock(etsObserverObjectSetLock_); + ani_ref global = nullptr; + if ((status = env->GlobalReference_Create(observerObj, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + etsObserverObjectSet_.emplace(std::make_shared(reinterpret_cast(global))); + } else { + TAG_LOGD(AAFwkTag::APPMGR, "observer exist"); + } +} + +void ETSAppForegroundStateObserver::RemoveAllEtsObserverObjects() +{ + std::lock_guard lock(etsObserverObjectSetLock_); + etsObserverObjectSet_.clear(); +} + +void ETSAppForegroundStateObserver::RemoveEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + auto observer = GetObserverObject(observerObj); + if (observer != nullptr) { + std::lock_guard lock(etsObserverObjectSetLock_); + etsObserverObjectSet_.erase(observer); + } +} + +std::shared_ptr ETSAppForegroundStateObserver::GetObserverObject(const ani_object &observerObject) +{ + if (observerObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return nullptr; + } + for (const auto& observer : etsObserverObjectSet_) { + if (observer && *observer == observerObject) { + return observer; + } + } + return nullptr; +} + +void ETSAppForegroundStateObserver::SetValid(bool valid) +{ + valid_ = valid; +} + +bool ETSAppForegroundStateObserver::IsEmpty() +{ + std::lock_guard lock(etsObserverObjectSetLock_); + return etsObserverObjectSet_.empty(); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp b/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp index dbdca40635a..f5122285e7e 100644 --- a/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp +++ b/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp @@ -19,6 +19,8 @@ #include "ability_manager_interface.h" #include "app_mgr_constants.h" #include "app_mgr_interface.h" +#include "ets_ability_first_frame_state_observer.h" +#include "ets_app_foreground_state_observer.h" #include "ipc_skeleton.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" @@ -38,16 +40,27 @@ namespace OHOS { namespace AppManagerSts { constexpr int32_t ERR_FAILURE = -1; +constexpr const char* ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE = "abilityFirstFrameState"; +constexpr const char* ON_OFF_TYPE_APP_FOREGROUND_STATE = "appForegroundState"; static const char* ON_SIGNATURE_FIRST = "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;Lescompat/Array;:D"; static const char* ON_SIGNATURE_SECOND = "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;:D"; - - +static const char* ON_SIGNATURE_THIRD + = "Lstd/core/String;Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;\ + Lstd/core/String;:V"; +static const char* ON_SIGNATURE_FORTH + = "Lstd/core/String;Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;:V"; static const char* OFF_SIGNATURE_FIRST = "Lstd/core/String;DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +static const char* OFF_SIGNATURE_SECOND + = "Lstd/core/String;Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;:V"; +static const char* OFF_SIGNATURE_THIRD + = "Lstd/core/String;Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;:V"; + class StsAppManager final { + static sptr observerForeground_; public: static OHOS::sptr GetAppManagerInstance() { @@ -898,7 +911,233 @@ static void OnOff(ani_env *env, [[maybe_unused]]ani_class aniClss) } TAG_LOGD(AAFwkTag::APPMGR, "NativeGetKeepAliveBundles end"); } + + static void OnOnAbilityFirstFrameStateInner(ani_env *env, ani_object aniObserver, const std::string& strBundleName) + { +#ifdef SUPPORT_SCREEN + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + sptr observer = + new (std::nothrow) AbilityRuntime::ETSAbilityFirstFrameStateObserver(aniVM); + if (observer == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr_ or observer"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance() + ->IsObserverObjectExist(aniObserver)) { + TAG_LOGE(AAFwkTag::APPMGR, "observer exist"); + return; + } + int32_t ret = abilityManager->RegisterAbilityFirstFrameStateObserver(observer, strBundleName); + TAG_LOGD(AAFwkTag::APPMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + observer->SetEtsObserverObject(aniObserver); + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance() + ->AddEtsAbilityFirstFrameStateObserver(observer); +#endif + } + + static void OnOnAbilityFirstFrameState(ani_env *env, ani_string type, ani_object aniObserver, + ani_object aniBundleName) + { +#ifdef SUPPORT_SCREEN + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAbilityFirstFrameState called"); + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType == ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AbilityFirstFrameStateObserver."); + return; + } + ani_status status = ANI_OK; + std::string strBundleName; + ani_boolean isUndefined; + if ((status = env->Reference_IsUndefined(aniBundleName, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined && !OHOS::AppExecFwk::GetStdString(env, + reinterpret_cast(aniBundleName), strBundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + OnOnAbilityFirstFrameStateInner(env, aniObserver, strBundleName); + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAbilityFirstFrameState end"); +#endif + } + + static void OnOnAppForegroundState(ani_env *env, ani_string type, ani_object observer) + { + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAppForegroundState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType == ON_OFF_TYPE_APP_FOREGROUND_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AppForegroundStateObserver."); + return; + } + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + //Create Observer + if (observerForeground_ == nullptr) { + observerForeground_ = new (std::nothrow) AbilityRuntime::ETSAppForegroundStateObserver(aniVM); + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appMgr or observer"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (observerForeground_->IsEmpty()) { + int32_t ret = appMgr->RegisterAppForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::APPMGR, "RegisterAppForegroundStateObserver ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::ThrowStsErrorByNativeErr(env, static_cast(ret)); + return; + } + } + observerForeground_->AddEtsObserverObject(observer); + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAppForegroundState end"); + } + + static void OnOffAbilityFirstFrameState(ani_env *env, ani_string type, ani_object aniObserver) + { +#ifdef SUPPORT_SCREEN + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAbilityFirstFrameState called"); + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType == ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AbilityFirstFrameStateObserver."); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniObserver, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (isUndefined) { + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance() + ->RemoveAllEtsObserverObjects(abilityManager); + } else { + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance() + ->RemoveEtsObserverObject(abilityManager, aniObserver); + } + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAbilityFirstFrameState end"); +#endif + } + +static void OnOffAppForegroundState(ani_env *env, ani_string type, ani_object observer) + { + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAppForegroundState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType == ON_OFF_TYPE_APP_FOREGROUND_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, + "Parse param observer failed, must be a AppForegroundStateObserver."); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer or appMgr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(observer, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (isUndefined) { + observerForeground_->RemoveAllEtsObserverObjects(); + } else { + observerForeground_->RemoveEtsObserverObject(observer); + } + if (observerForeground_->IsEmpty()) { + int32_t ret = appMgr->UnregisterAppForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::APPMGR, "ret: %{public}d.", ret); + if (ret != NO_ERROR) { + AbilityRuntime::ThrowStsErrorByNativeErr(env, static_cast(ret)); + } + } + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAppForegroundState end"); + } }; //StsAppManager +sptr StsAppManager::observerForeground_ = nullptr; void StsAppManagerRegistryInit(ani_env *env) { @@ -961,7 +1200,15 @@ void StsAppManagerRegistryInit(ani_env *env) ani_native_function {"nativeSetKeepAliveForBundle", nullptr, reinterpret_cast(StsAppManager::NativeSetKeepAliveForBundle)}, ani_native_function {"nativeGetKeepAliveBundles", nullptr, - reinterpret_cast(StsAppManager::NativeGetKeepAliveBundles)} + reinterpret_cast(StsAppManager::NativeGetKeepAliveBundles)}, + ani_native_function {"nativeOnAbilityFirstFrameState", ON_SIGNATURE_THIRD, + reinterpret_cast(StsAppManager::OnOnAbilityFirstFrameState)}, + ani_native_function {"nativeOnAppForeGroundState", ON_SIGNATURE_FORTH, + reinterpret_cast(StsAppManager::OnOnAppForegroundState)}, + ani_native_function {"nativeOffAbilityFirstFrameState", OFF_SIGNATURE_SECOND, + reinterpret_cast(StsAppManager::OnOffAbilityFirstFrameState)}, + ani_native_function {"nativeOffAppForeGroundState", OFF_SIGNATURE_THIRD, + reinterpret_cast(StsAppManager::OnOffAppForegroundState)} }; status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); diff --git a/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp b/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp index dec94521450..d64c4413d7e 100644 --- a/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp +++ b/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp @@ -984,6 +984,82 @@ ani_object CreateKeepAliveInfoArray(ani_env *env, const std::vectorObject_SetFieldByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, abilityFirstFrameStateData.bundleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "moduleName", + OHOS::AppExecFwk::GetAniString(env, abilityFirstFrameStateData.moduleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "moduleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "abilityName", + OHOS::AppExecFwk::GetAniString(env, abilityFirstFrameStateData.abilityName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Double(object, "appIndex", + static_cast(abilityFirstFrameStateData.appIndex))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "appIndex failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Boolean(object, "isColdStart", + abilityFirstFrameStateData.coldStart)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isColdStart failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapAbilityFirstFrameStateData(ani_env *env, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass("Lapplication/AbilityFirstFrameStateData/AbilityFirstFrameStateDataInner;", &cls) + ) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find class failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New AbilityFirstFrameStateData failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetAbilityFirstFrameStateData(env, object, abilityFirstFrameStateData)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetAbilityFirstFrameStateData failed"); + return nullptr; + } + return object; +} +#endif } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/app_manager/src/sts_app_state_observer.cpp b/frameworks/ets/ani/app_manager/src/sts_app_state_observer.cpp new file mode 100644 index 00000000000..9d8cfab8cca --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/sts_app_state_observer.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2022-2024 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 "sts_app_state_observer.h" +#include "hilog_tag_wrapper.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "sts_app_manager_utils.h" +#include "ani_common_ability_state_data.h" +namespace OHOS { +namespace AbilityRuntime { + +StsAppStateObserver::StsAppStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +StsAppStateObserver::~StsAppStateObserver() = default; + +void StsAppStateObserver::OnForegroundApplicationChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "invalid appmgr"); + return; + } + HandleOnForegroundApplicationChanged(appStateData); +} + +void StsAppStateObserver::HandleOnForegroundApplicationChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsVm_ nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return; + } + auto tmpMap = stsObserverObjectMap_; + for (auto &item : tmpMap) { + auto appStateDataObj = AppManagerSts::WrapAppStateData(env, appStateData); + const char *signature = "Lapplication/AppStateData/AppStateData;:V"; + CallStsFunction(env, item.second, "onForegroundApplicationChanged", signature, appStateDataObj); + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } +} + +void StsAppStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may has cancelled storage"); + return; + } + HandleOnAbilityStateChanged(abilityStateData); +} + +void StsAppStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsVm_ nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return; + } + auto tmpMap = stsObserverObjectMap_; + for (auto &item : tmpMap) { + auto abilityStateDataObj = OHOS::AppExecFwk::WrapAbilityStateData(env, abilityStateData); + const char *signature = "Lapplication/AbilityStateData/AbilityStateData;:V"; + CallStsFunction(env, item.second, "onAbilityStateChanged", signature, abilityStateDataObj); + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } +} + +void StsAppStateObserver::OnExtensionStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + HandleOnExtensionStateChanged(abilityStateData); +} + +void StsAppStateObserver::HandleOnExtensionStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); +} + +void StsAppStateObserver::OnProcessCreated(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appmgr may has cancelled storage"); + return; + } + HandleOnProcessCreated(processData); +} + +void StsAppStateObserver::HandleOnProcessCreated(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); +} + +void StsAppStateObserver::OnProcessStateChanged(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + HandleOnProcessStateChanged(processData); +} + +void StsAppStateObserver::HandleOnProcessStateChanged(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsVm_ nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "wyh status : %{public}d", status); + return; + } + auto tmpMap = stsObserverObjectMap_; + for (auto &item : tmpMap) { + auto processDataObj = AppManagerSts::WrapProcessData(env, processData); + const char *signature = "Lapplication/ProcessData/ProcessData;:V"; + CallStsFunction(env, item.second, "onProcessStateChanged", signature, processDataObj); + } + if (etsVm_->DetachCurrentThread() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } +} + +void StsAppStateObserver::OnProcessDied(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appmgr may destroyed"); + return; + } + HandleOnProcessDied(processData); +} + +void StsAppStateObserver::HandleOnProcessDied(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); +} + +void StsAppStateObserver::OnAppStarted(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + HandleOnAppStarted(appStateData); +} + +void StsAppStateObserver::HandleOnAppStarted(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, + "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); +} + +void StsAppStateObserver::OnAppStopped(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + HandleOnAppStopped(appStateData); +} + +void StsAppStateObserver::HandleOnAppStopped(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, + "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); +} + +void StsAppStateObserver::CallStsFunction(ani_env* env, ani_object StsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + status = env->FindClass("Lapplication/ApplicationStateObserver/ApplicationStateObserver;", &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find ApplicationStateObserver failed status : %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "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::UI_EXT, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::APPMGR, "end"); + return; +} + +void StsAppStateObserver::AddStsObserverObject(ani_env *env, const int32_t observerId, ani_object StsObserverObject) +{ + ani_ref global = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(StsObserverObject, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + stsObserverObjectMap_.emplace(observerId, reinterpret_cast(global)); +} + +bool StsAppStateObserver::RemoveStsObserverObject(const int32_t observerId) +{ + bool result = (stsObserverObjectMap_.erase(observerId) == 1); + return result; +} + +bool StsAppStateObserver::FindObserverByObserverId(const int32_t observerId) +{ + auto item = stsObserverObjectMap_.find(observerId); + bool isExist = (item != stsObserverObjectMap_.end()); + return isExist; +} + +size_t StsAppStateObserver::GetStsObserverMapSize() +{ + size_t length = stsObserverObjectMap_.size(); + return length; +} + +void StsAppStateObserver::SetValid(const bool valid) +{ + valid_ = valid; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.appManager.ets b/frameworks/ets/ets/@ohos.app.ability.appManager.ets index fe4df6bd34b..adcbdfd803a 100644 --- a/frameworks/ets/ets/@ohos.app.ability.appManager.ets +++ b/frameworks/ets/ets/@ohos.app.ability.appManager.ets @@ -22,6 +22,9 @@ import _ProcessData from 'application.ProcessData'; import _ApplicationStateObserver from 'application.ApplicationStateObserver'; import AsyncCallbackWrapper from './utils/AbilityUtils'; import bundleManager from '@ohos.bundle.bundleManager'; +import _AppForegroundStateObserver from 'application.AppForegroundStateObserver'; +import { AbilityFirstFrameStateObserver as _AbilityFirstFrameStateObserver } from 'application.AbilityFirstFrameStateObserver'; +import { AbilityFirstFrameStateData as _AbilityFirstFrameStateData } from 'application.AbilityFirstFrameStateData'; export default namespace appManager { loadLibrary("ability_app_manager_ani_kit.z") @@ -32,6 +35,9 @@ export type AppStateData = _AppStateData; export type RunningMultiAppInfo = _RunningMultiAppInfo; export type ProcessData = _ProcessData; export type ApplicationStateObserver = _ApplicationStateObserver; +export type AppForegroundStateObserver = _AppForegroundStateObserver; +export type AbilityFirstFrameStateObserver = _AbilityFirstFrameStateObserver; +export type AbilityFirstFrameStateData = _AbilityFirstFrameStateData; export enum PreloadMode { PRESS_DOWN @@ -352,6 +358,26 @@ export function killProcessesByBundleName(bundleName: string, clearPageStack: bo return p; } +export native function nativeOnAbilityFirstFrameState(type: string, observer: AbilityFirstFrameStateObserver, bundleName?: string) : void; +export function on(type: 'abilityFirstFrameState', observer: AbilityFirstFrameStateObserver, bundleName?: string) : void { + appManager.nativeOnAbilityFirstFrameState('abilityFirstFrameState', observer, bundleName); +} + +export native function nativeOffAbilityFirstFrameState(type: string, observer?: AbilityFirstFrameStateObserver) : void; +export function off(type: 'abilityFirstFrameState', observer?: AbilityFirstFrameStateObserver) : void { + appManager.nativeOffAbilityFirstFrameState('abilityFirstFrameState', observer); +} + +export native function nativeOnAppForeGroundState(type: string, observer: AppForegroundStateObserver) : void; +export function on(type: 'appForegroundState', observer: AppForegroundStateObserver) : void { + appManager.nativeOnAppForeGroundState('appForegroundState', observer); +} + +export native function nativeOffAppForeGroundState(type: string, observer?: AppForegroundStateObserver) : void; +export function off(type: 'appForegroundState', observer?: AppForegroundStateObserver) : void { + appManager.nativeOffAppForeGroundState('appForegroundState', observer); +} + export native function nativeKillProcessWithAccountSync(bundleName: string, accountId: number, callback: AsyncCallbackWrapper) : void; export function killProcessWithAccount(bundleName: string, accountId: number, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index cf3a702bf83..abfa3f4c07c 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -883,6 +883,54 @@ ohos_prebuilt_etc("ability_runtime_AbilityRunningInfo_abc_etc") { deps = [ ":ability_runtime_AbilityRunningInfo_abc" ] } +generate_static_abc("ability_first_frame_state_data_abc") { + base_url = "./" + files = [ "./application/AbilityFirstFrameStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_first_frame_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_first_frame_state_data_abc_etc") { + source = "$target_out_dir/ability_first_frame_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_first_frame_state_data_abc" ] +} + +generate_static_abc("ability_first_frame_state_observer_abc") { + base_url = "./" + files = [ "./application/AbilityFirstFrameStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_first_frame_state_observer_abc.abc" +} + +ohos_prebuilt_etc("ability_first_frame_state_observer_abc_etc") { + source = "$target_out_dir/ability_first_frame_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_first_frame_state_observer_abc" ] +} + +generate_static_abc("app_foreground_state_observer_abc") { + base_url = "./" + files = [ "./application/AppForegroundStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/app_foreground_state_observer_abc.abc" +} + +ohos_prebuilt_etc("app_foreground_state_observer_abc_etc") { + source = "$target_out_dir/app_foreground_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":app_foreground_state_observer_abc" ] +} + group("ets_packages") { deps = [ ":ability_ability_application_abc_etc", @@ -892,6 +940,8 @@ group("ets_packages") { ":ability_delegator_application_testRunner_abc_etc", ":ability_delegator_args_abc_etc", ":ability_delegator_registry_abc_etc", + ":ability_first_frame_state_data_abc_etc" + ":ability_first_frame_state_observer_abc_etc", ":ability_runtime_abilityResult_abc_etc", ":ability_runtime_ability_callee_abc_etc", ":ability_runtime_ability_caller_abc_etc", @@ -937,5 +987,6 @@ group("ets_packages") { ":ui_extension_ability_ani_etc", ":ability_runtime_OpenLink_Options_abc_etc", ":ability_runtime_AbilityRunningInfo_abc_etc", + ":app_foreground_state_observer_abc_etc", ] } diff --git a/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets b/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets new file mode 100644 index 00000000000..7ef3d93767b --- /dev/null +++ b/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets @@ -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. + */ + +export interface AbilityFirstFrameStateData { + bundleName: string; + moduleName: string; + abilityName: string; + appIndex: number; + isColdStart: boolean; +} + +export default class AbilityFirstFrameStateDataInner implements AbilityFirstFrameStateData { + bundleName: string = ''; + moduleName: string = ''; + abilityName: string = ''; + appIndex: number; + isColdStart: boolean; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets b/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets new file mode 100644 index 00000000000..3ecbc749a33 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets @@ -0,0 +1,24 @@ +/* + * 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 { AbilityFirstFrameStateData } from 'application.AbilityFirstFrameStateData'; + +export interface AbilityFirstFrameStateObserver { + onAbilityFirstFrameDrawn(data: AbilityFirstFrameStateData): void; +} + +export default class AbilityFirstFrameStateObserverInner implements AbilityFirstFrameStateObserver { + onAbilityFirstFrameDrawn(data: AbilityFirstFrameStateData): void {} +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets b/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets new file mode 100644 index 00000000000..c5652df4a32 --- /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 diff --git a/frameworks/ets/ets/application/AppForegroundStateObserver.ets b/frameworks/ets/ets/application/AppForegroundStateObserver.ets new file mode 100644 index 00000000000..c72142bd5b0 --- /dev/null +++ b/frameworks/ets/ets/application/AppForegroundStateObserver.ets @@ -0,0 +1,20 @@ +/* + * 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 AppStateData from 'application.AppStateData'; + +export default class AppForegroundStateObserver { + onAppStateChanged(appStateData: AppStateData): void {} +} \ No newline at end of file -- Gitee