diff --git a/frameworks/js/napi/ability/ability.js b/frameworks/js/napi/ability/ability.js index 822964b91a..c043d6d578 100644 --- a/frameworks/js/napi/ability/ability.js +++ b/frameworks/js/napi/ability/ability.js @@ -25,6 +25,9 @@ class Ability { onWindowStageDestroy() { } onForeground(want) { } onBackground() { } + onPrepareToTerminate() { + return false; + } onMemoryLevel(level) { } onWindowStageRestore(windowStage) { } onCallRequest() { diff --git a/frameworks/native/ability/native/ability.cpp b/frameworks/native/ability/native/ability.cpp index 9dadc03fab..8e6d4db8e8 100644 --- a/frameworks/native/ability/native/ability.cpp +++ b/frameworks/native/ability/native/ability.cpp @@ -1596,6 +1596,12 @@ void Ability::OnBackground() HiSysEventType::BEHAVIOR, eventInfo); } +bool Ability::OnPrepareTerminate() +{ + HILOG_DEBUG("call"); + return false; +} + void Ability::OnKeyDown(const std::shared_ptr& keyEvent) { HILOG_DEBUG("Ability::OnKeyDown called"); diff --git a/frameworks/native/ability/native/ability_impl.cpp b/frameworks/native/ability/native/ability_impl.cpp index 552ca771bd..7809e317f6 100644 --- a/frameworks/native/ability/native/ability_impl.cpp +++ b/frameworks/native/ability/native/ability_impl.cpp @@ -299,6 +299,18 @@ void AbilityImpl::CommandAbility(const Want &want, bool restart, int startId) HILOG_DEBUG("%{public}s end.", __func__); } +bool AbilityImpl::PrepareTerminateAbility() +{ + HILOG_DEBUG("call"); + if (ability_ == nullptr) { + HILOG_ERROR("ability_ is nullptr."); + return false; + } + bool ret = ability_->OnPrepareTerminate(); + HILOG_DEBUG("end, ret = %{public}d", ret); + return ret; +} + int AbilityImpl::GetCurrentState() { return lifecycleState_; diff --git a/frameworks/native/ability/native/ability_runtime/js_ability.cpp b/frameworks/native/ability/native/ability_runtime/js_ability.cpp index 54f3be4d8a..e1be87940b 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability.cpp @@ -496,6 +496,23 @@ void JsAbility::OnBackground() HILOG_DEBUG("OnBackground end, ability is %{public}s.", GetAbilityName().c_str()); } +bool JsAbility::OnPrepareTerminate() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HILOG_DEBUG("call, ability: %{public}s.", GetAbilityName().c_str()); + Ability::OnPrepareTerminate(); + + NativeValue *jsValue = CallObjectMethod("onPrepareToTerminate", nullptr, 0, true); + auto numberValue = ConvertNativeValueTo(jsValue); + if (numberValue == nullptr) { + HILOG_ERROR("numberValue is nullptr."); + return false; + } + bool ret = (bool)(*numberValue); + HILOG_DEBUG("end, ret = %{public}d", ret); + return ret; +} + std::unique_ptr JsAbility::CreateAppWindowStage() { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/frameworks/native/ability/native/ability_thread.cpp b/frameworks/native/ability/native/ability_thread.cpp index 193c92dd11..b2fefe9f5d 100644 --- a/frameworks/native/ability/native/ability_thread.cpp +++ b/frameworks/native/ability/native/ability_thread.cpp @@ -808,6 +808,18 @@ void AbilityThread::ScheduleCommandAbility(const Want &want, bool restart, int s HILOG_DEBUG("AbilityThread::ScheduleCommandAbility end"); } +bool AbilityThread::SchedulePrepareTerminateAbility() +{ + HILOG_DEBUG("call"); + if (abilityImpl_ == nullptr) { + HILOG_ERROR("abilityImpl_ is nullptr."); + return true; + } + bool ret = abilityImpl_->PrepareTerminateAbility(); + HILOG_DEBUG("end, ret = %{public}d", ret); + return ret; +} + void AbilityThread::SendResult(int requestCode, int resultCode, const Want &want) { HILOG_DEBUG("AbilityThread::SendResult begin"); diff --git a/interfaces/inner_api/ability_manager/BUILD.gn b/interfaces/inner_api/ability_manager/BUILD.gn index 47aeae3414..7b16f7c215 100644 --- a/interfaces/inner_api/ability_manager/BUILD.gn +++ b/interfaces/inner_api/ability_manager/BUILD.gn @@ -32,6 +32,7 @@ config("ability_manager_public_config") { "${ability_runtime_path}/interfaces/kits/native/ability/native", "${bundlefwk_inner_api_path}/appexecfwk_base/include", "${bundlefwk_inner_api_path}/appexecfwk_core/include/bundlemgr", + "${ability_runtime_innerkits_path}/ability_manager/include", "${ability_runtime_innerkits_path}/app_manager/include/appmgr", "${ability_runtime_path}/interfaces/kits/native/appkit/app", "${ability_runtime_path}/interfaces/kits/native/appkit", @@ -83,6 +84,8 @@ ohos_shared_library("ability_manager") { "${ability_runtime_services_path}/abilitymgr/src/mission_listener_proxy.cpp", "${ability_runtime_services_path}/abilitymgr/src/mission_listener_stub.cpp", "${ability_runtime_services_path}/abilitymgr/src/mission_snapshot.cpp", + "${ability_runtime_services_path}/abilitymgr/src/prepare_terminate_callback_proxy.cpp", + "${ability_runtime_services_path}/abilitymgr/src/prepare_terminate_callback_stub.cpp", "${ability_runtime_services_path}/abilitymgr/src/remote_mission_listener_proxy.cpp", "${ability_runtime_services_path}/abilitymgr/src/remote_mission_listener_stub.cpp", "${ability_runtime_services_path}/abilitymgr/src/sender_info.cpp", diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_client.h b/interfaces/inner_api/ability_manager/include/ability_manager_client.h index 926f06d7f8..effcd13bb7 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -754,6 +754,14 @@ public: */ ErrCode RegisterSnapshotHandler(const sptr& handler); + /** + * PrepareTerminateAbility with want, if terminate, return want from ability manager service. + * + * @param token Ability token. + * @param callback callback. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode PrepareTerminateAbility(const sptr &token, sptr &callback); #ifdef SUPPORT_GRAPHICS /** * Set mission label of this ability. diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h index 372923b2af..76f61ea0e3 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -30,6 +30,7 @@ #include "iability_controller.h" #include "iacquire_share_data_callback_interface.h" #include "icomponent_interception.h" +#include "iprepare_terminate_callback_interface.h" #include "mission_listener_interface.h" #include "mission_info.h" #include "mission_snapshot.h" @@ -674,6 +675,18 @@ public: * @param abilityToken Indidate token of ability. */ virtual void CompleteFirstFrameDrawing(const sptr &abilityToken) = 0; + + /** + * PrepareTerminateAbility, prepare terminate the special ability. + * + * @param token, the token of the ability to terminate. + * @param callback callback. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PrepareTerminateAbility(const sptr &token, sptr &callback) + { + return 0; + } #endif virtual int GetAbilityRunningInfos(std::vector &info) = 0; @@ -1131,6 +1144,9 @@ public: // ipc id for set rootSceneSession (64) SET_ROOTSSCENESESSION, + // prepare terminate ability (65) + PREPARE_TERMINATE_ABILITY, + // ipc id 1001-2000 for DMS // ipc id for starting ability (1001) START_ABILITY = 1001, diff --git a/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h b/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h index b7c3c94eba..9c4bbe4264 100644 --- a/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_scheduler_interface.h @@ -87,6 +87,11 @@ public: */ virtual void ScheduleCommandAbility(const Want &want, bool restart, int startId) = 0; + /** + * SchedulePrepareTerminateAbility, schedule ability to prepare terminate. + */ + virtual bool SchedulePrepareTerminateAbility() = 0; + /* * ScheduleSaveAbilityState, scheduling save ability state. */ @@ -377,7 +382,10 @@ public: SCHEDULE_CALL, - SCHEDULE_SHARE_DATA + SCHEDULE_SHARE_DATA, + + // ipc id for scheduling service ability to prepare terminate (30) + SCHEDULE_ABILITY_PREPARE_TERMINATE }; }; } // namespace AAFwk diff --git a/interfaces/inner_api/ability_manager/include/iprepare_terminate_callback_interface.h b/interfaces/inner_api/ability_manager/include/iprepare_terminate_callback_interface.h new file mode 100644 index 0000000000..284bb943d8 --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/iprepare_terminate_callback_interface.h @@ -0,0 +1,36 @@ +/* + * 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_PREPARE_TERMINATE_CALLBACK_INTERFACE_H +#define OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_INTERFACE_H + +#include "iremote_broker.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AAFwk { +class IPrepareTerminateCallback : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.prepareTerminateCallback"); + virtual void DoPrepareTerminate() {}; + enum { + // ipc id for DoPrepareTerminate (1) + ON_DO_PREPARE_TERMINATE = 1, + CODE_MAX + }; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_INTERFACE_H diff --git a/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_proxy.h b/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_proxy.h new file mode 100644 index 0000000000..5c9af96bb0 --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_proxy.h @@ -0,0 +1,38 @@ +/* + * 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_PREPARE_TERMINATE_CALLBACK_PROXY_H +#define OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_PROXY_H + +#include "iremote_proxy.h" +#include "iprepare_terminate_callback_interface.h" + +namespace OHOS { +namespace AAFwk { +class PrepareTerminateCallbackProxy : public IRemoteProxy { +public: + explicit PrepareTerminateCallbackProxy + (const sptr &impl) : IRemoteProxy(impl) {} + + virtual ~PrepareTerminateCallbackProxy() {} + + virtual void DoPrepareTerminate() override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_PROXY_H diff --git a/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_stub.h b/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_stub.h new file mode 100644 index 0000000000..81d0e5c7ed --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/prepare_terminate_callback_stub.h @@ -0,0 +1,41 @@ +/* + * 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_PREPARE_TERMINATE_CALLBACK_STUB_H +#define OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_STUB_H + +#include +#include "iprepare_terminate_callback_interface.h" +#include "iremote_stub.h" +#include "message_parcel.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +class PrepareTerminateCallbackStub : public IRemoteStub { +public: + PrepareTerminateCallbackStub(); + virtual ~PrepareTerminateCallbackStub(); + int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int DoPrepareTerminateInner(MessageParcel &data, MessageParcel &reply); + using RequestFuncType = int (PrepareTerminateCallbackStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_PREPARE_TERMINATE_CALLBACK_STUB_H diff --git a/interfaces/kits/native/ability/native/ability.h b/interfaces/kits/native/ability/native/ability.h index 6ad8995a3e..b497eb1e74 100644 --- a/interfaces/kits/native/ability/native/ability.h +++ b/interfaces/kits/native/ability/native/ability.h @@ -878,6 +878,13 @@ public: */ virtual void OnBackground(); + /** + * @brief Called when ability prepare terminate. + * + * @return Return true if ability need to stop terminating; return false if ability need to terminate. + */ + virtual bool OnPrepareTerminate(); + /** * @brief Called when a key is pressed. When any component in the Ability gains focus, the key-down event for * the component will be handled first. This callback will not be invoked if the callback triggered for the diff --git a/interfaces/kits/native/ability/native/ability_impl.h b/interfaces/kits/native/ability/native/ability_impl.h index 52f1d2ae88..0ad8ff7625 100644 --- a/interfaces/kits/native/ability/native/ability_impl.h +++ b/interfaces/kits/native/ability/native/ability_impl.h @@ -71,6 +71,13 @@ public: */ void CommandAbility(const Want &want, bool restart, int startId); + /** + * @brief Prepare terminate the ability. + * + * @return Return true if ability need be terminated; return false if ability need stop terminating. + */ + bool PrepareTerminateAbility(); + /** * @brief Gets the current Ability status. * diff --git a/interfaces/kits/native/ability/native/ability_runtime/js_ability.h b/interfaces/kits/native/ability/native/ability_runtime/js_ability.h index c311dafbf5..28da64b28b 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/js_ability.h +++ b/interfaces/kits/native/ability/native/ability_runtime/js_ability.h @@ -78,6 +78,7 @@ public: void OnForeground(const Want &want) override; void OnBackground() override; + bool OnPrepareTerminate() override; std::shared_ptr GetJsWindowStage(); const JsRuntime& GetJsRuntime(); diff --git a/interfaces/kits/native/ability/native/ability_thread.h b/interfaces/kits/native/ability/native/ability_thread.h index 504c91d2ee..6e0edbb0fe 100644 --- a/interfaces/kits/native/ability/native/ability_thread.h +++ b/interfaces/kits/native/ability/native/ability_thread.h @@ -154,6 +154,11 @@ public: */ void ScheduleCommandAbility(const Want &want, bool restart, int startId); + /** + * @description: Provide operating system PrepareTerminateAbility information to the observer + */ + bool SchedulePrepareTerminateAbility(); + /** * @description: Provide operating system SaveabilityState information to the observer */ diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index 47e1ed2241..8f2d16b0b3 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -561,6 +561,9 @@ public: virtual int RegisterWindowManagerServiceHandler(const sptr& handler) override; virtual void CompleteFirstFrameDrawing(const sptr &abilityToken) override; + + virtual int PrepareTerminateAbility( + const sptr &token, sptr &callback) override; #endif virtual int GetAbilityRunningInfos(std::vector &info) override; diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index cf0a8d3700..15aa3e6b51 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -768,6 +768,9 @@ public: sptr GetWMSHandler() const; + virtual int PrepareTerminateAbility(const sptr &token, + sptr &callback) override; + void HandleFocused(const sptr &focusChangeInfo); void HandleUnfocused(const sptr &focusChangeInfo); diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index c15bc81c5f..294d377cd1 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -185,6 +185,7 @@ private: int SetMissionIconInner(MessageParcel &data, MessageParcel &reply); int RegisterWindowManagerServiceHandlerInner(MessageParcel &data, MessageParcel &reply); int CompleteFirstFrameDrawingInner(MessageParcel &data, MessageParcel &reply); + int PrepareTerminateAbilityInner(MessageParcel &data, MessageParcel &reply); #endif #ifdef ABILITY_COMMAND_FOR_TEST diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 1c8b16d321..ad4f8aac30 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -329,6 +329,13 @@ public: */ void BackgroundAbility(const Closure &task); + /** + * prepare terminate ability. + * + * @return Returns true on stop terminating; returns false on terminate. + */ + bool PrepareTerminateAbility(); + /** * terminate ability. * diff --git a/services/abilitymgr/include/ability_scheduler_proxy.h b/services/abilitymgr/include/ability_scheduler_proxy.h index 8e4df81d46..55102aefb7 100644 --- a/services/abilitymgr/include/ability_scheduler_proxy.h +++ b/services/abilitymgr/include/ability_scheduler_proxy.h @@ -85,6 +85,11 @@ public: */ void ScheduleCommandAbility(const Want &want, bool restart, int startId) override; + /* + * SchedulePrepareTerminateAbility, schedule service ability to prepare terminate. + */ + bool SchedulePrepareTerminateAbility() override; + /* * ScheduleSaveAbilityState, scheduling save ability state. */ diff --git a/services/abilitymgr/include/ability_scheduler_stub.h b/services/abilitymgr/include/ability_scheduler_stub.h index ef72f3f6cd..5e5d0f5b33 100644 --- a/services/abilitymgr/include/ability_scheduler_stub.h +++ b/services/abilitymgr/include/ability_scheduler_stub.h @@ -42,6 +42,7 @@ private: int ConnectAbilityInner(MessageParcel &data, MessageParcel &reply); int DisconnectAbilityInner(MessageParcel &data, MessageParcel &reply); int CommandAbilityInner(MessageParcel &data, MessageParcel &reply); + int PrepareTerminateAbilityInner(MessageParcel &data, MessageParcel &reply); int SaveAbilityStateInner(MessageParcel &data, MessageParcel &reply); int RestoreAbilityStateInner(MessageParcel &data, MessageParcel &reply); int GetFileTypesInner(MessageParcel &data, MessageParcel &reply); diff --git a/services/abilitymgr/include/lifecycle_deal.h b/services/abilitymgr/include/lifecycle_deal.h index 3c8de9f225..e6a6b62b4a 100644 --- a/services/abilitymgr/include/lifecycle_deal.h +++ b/services/abilitymgr/include/lifecycle_deal.h @@ -61,6 +61,7 @@ public: void ContinueAbility(const std::string& deviceId, uint32_t versionCode); void NotifyContinuationResult(int32_t result); void ShareData(const int32_t &uniqueId); + bool PrepareTerminateAbility(); private: sptr GetScheduler(); diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index d14d32ed1a..0602b68b78 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -839,6 +839,21 @@ void AbilityManagerClient::CompleteFirstFrameDrawing(const sptr & CHECK_POINTER_RETURN(abms); abms->CompleteFirstFrameDrawing(abilityToken); } + +ErrCode AbilityManagerClient::PrepareTerminateAbility(const sptr &token, + sptr &callback) +{ + if (callback == nullptr) { + HILOG_ERROR("callback is nullptr."); + return ERR_INVALID_VALUE; + } + auto abms = GetAbilityManager(); + if (abms == nullptr) { + HILOG_ERROR("abms is nullptr."); + return ERR_INVALID_VALUE; + } + return abms->PrepareTerminateAbility(token, callback); +} #endif ErrCode AbilityManagerClient::DoAbilityForeground(const sptr &token, uint32_t flag) diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index f00a34e5e1..4af13c9adb 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -2743,6 +2743,51 @@ void AbilityManagerProxy::CompleteFirstFrameDrawing(const sptr &a HILOG_ERROR("%{public}s: send request error: %{public}d", __func__, error); } } + +int AbilityManagerProxy::PrepareTerminateAbility(const sptr &token, + sptr &callback) +{ + if (!callback) { + HILOG_ERROR("callback is nullptr."); + return INNER_ERR; + } + int error = 0; + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("write interface token failed."); + return INNER_ERR; + } + if (token) { + if (!data.WriteBool(true) || !data.WriteRemoteObject(token)) { + HILOG_ERROR("write token failed."); + return INNER_ERR; + } + } else { + if (!data.WriteBool(false)) { + HILOG_ERROR("write token failed."); + return INNER_ERR; + } + } + if (!data.WriteRemoteObject(callback->AsObject())) { + HILOG_ERROR("weite callback failed."); + return INNER_ERR; + } + + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("remote is nullptr."); + return INNER_ERR; + } + error = remote->SendRequest(IAbilityManager::PREPARE_TERMINATE_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("send request failed. error: %{public}d", error); + return error; + } + + return reply.ReadInt32(); +} #endif int AbilityManagerProxy::GetAbilityRunningInfos(std::vector &info) diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 0c4f23db74..90ce68fec8 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -138,6 +138,7 @@ const int32_t GET_PARAMETER_OTHER = -1; const int32_t SIZE_10 = 10; const int32_t ACCOUNT_MGR_SERVICE_UID = 3058; const int32_t DMS_UID = 5522; +const int32_t PREPARE_TERMINATE_TIMEOUT_MULTIPLE = 10; const std::string BUNDLE_NAME_KEY = "bundleName"; const std::string DM_PKG_NAME = "ohos.distributedhardware.devicemanager"; const std::string ACTION_CHOOSE = "ohos.want.action.select"; @@ -6232,6 +6233,53 @@ bool AbilityManagerService::CheckWindowMode(int32_t windowMode, return false; } +int AbilityManagerService::PrepareTerminateAbility(const sptr &token, + sptr &callback) +{ + HILOG_DEBUG("call"); + if (callback == nullptr) { + HILOG_ERROR("callback is nullptr."); + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + if (abilityRecord == nullptr) { + HILOG_ERROR("record is nullptr."); + callback->DoPrepareTerminate(); + return ERR_INVALID_VALUE; + } + + if (!JudgeSelfCalled(abilityRecord)) { + HILOG_ERROR("Not self call."); + callback->DoPrepareTerminate(); + return CHECK_PERMISSION_FAILED; + } + + auto type = abilityRecord->GetAbilityInfo().type; + if (type != AppExecFwk::AbilityType::PAGE) { + HILOG_ERROR("Only support PAGE."); + callback->DoPrepareTerminate(); + return RESOLVE_CALL_ABILITY_TYPE_ERR; + } + + auto timeoutTask = [&callback]() { + callback->DoPrepareTerminate(); + }; + int prepareTerminateTimeout = + AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * PREPARE_TERMINATE_TIMEOUT_MULTIPLE; + if (handler_) { + handler_->PostTask(timeoutTask, "PrepareTermiante_" + std::to_string(abilityRecord->GetAbilityRecordId()), + prepareTerminateTimeout); + } + + bool res = abilityRecord->PrepareTerminateAbility(); + if (!res) { + callback->DoPrepareTerminate(); + } + handler_->RemoveTask("PrepareTermiante_" + std::to_string(abilityRecord->GetAbilityRecordId())); + return ERR_OK; +} + void AbilityManagerService::HandleFocused(const sptr &focusChangeInfo) { HILOG_INFO("handle focused event"); diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index a8411868e9..1f36525979 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -167,6 +167,7 @@ void AbilityManagerStub::ThirdStepInit() requestFuncMap_[MINIMIZE_UI_EXTENSION_ABILITY] = &AbilityManagerStub::MinimizeUIExtensionAbilityInner; requestFuncMap_[TERMINATE_UI_EXTENSION_ABILITY] = &AbilityManagerStub::TerminateUIExtensionAbilityInner; requestFuncMap_[CONNECT_UI_EXTENSION_ABILITY] = &AbilityManagerStub::ConnectUIExtensionAbilityInner; + requestFuncMap_[PREPARE_TERMINATE_ABILITY] = &AbilityManagerStub::PrepareTerminateAbilityInner; #endif requestFuncMap_[REQUEST_DIALOG_SERVICE] = &AbilityManagerStub::HandleRequestDialogService; requestFuncMap_[SET_COMPONENT_INTERCEPTION] = &AbilityManagerStub::SetComponentInterceptionInner; @@ -1965,6 +1966,26 @@ int AbilityManagerStub::CompleteFirstFrameDrawingInner(MessageParcel &data, Mess CompleteFirstFrameDrawing(abilityToken); return 0; } + +int AbilityManagerStub::PrepareTerminateAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + HILOG_DEBUG("call"); + sptr token = nullptr; + if (data.ReadBool()) { + token = data.ReadRemoteObject(); + } + sptr callback = iface_cast(data.ReadRemoteObject()); + if (callback == nullptr) { + HILOG_ERROR("callback is nullptr"); + return ERR_NULL_OBJECT; + } + int result = PrepareTerminateAbility(token, callback); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("end faild. err: %{public}d", result); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} #endif int32_t AbilityManagerStub::IsValidMissionIdsInner(MessageParcel &data, MessageParcel &reply) diff --git a/services/abilitymgr/src/ability_record.cpp b/services/abilitymgr/src/ability_record.cpp index 2a05d34a44..e698692c9c 100644 --- a/services/abilitymgr/src/ability_record.cpp +++ b/services/abilitymgr/src/ability_record.cpp @@ -1031,6 +1031,16 @@ void AbilityRecord::BackgroundAbility(const Closure &task) lifecycleDeal_->BackgroundNew(want_, lifeCycleStateInfo_, sessionInfo_); } +bool AbilityRecord::PrepareTerminateAbility() +{ + HILOG_DEBUG("call"); + if (lifecycleDeal_ == nullptr) { + HILOG_ERROR("lifecycleDeal_ is nullptr."); + return false; + } + return lifecycleDeal_->PrepareTerminateAbility(); +} + int AbilityRecord::TerminateAbility() { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/services/abilitymgr/src/ability_scheduler_proxy.cpp b/services/abilitymgr/src/ability_scheduler_proxy.cpp index 4c337f7825..2e3a87615a 100644 --- a/services/abilitymgr/src/ability_scheduler_proxy.cpp +++ b/services/abilitymgr/src/ability_scheduler_proxy.cpp @@ -174,6 +174,29 @@ void AbilitySchedulerProxy::ScheduleCommandAbility(const Want &want, bool restar } } +bool AbilitySchedulerProxy::SchedulePrepareTerminateAbility() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("fail to write interface."); + return false; + } + + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("Remote() is NULL"); + return false; + } + int32_t err = remote->SendRequest(IAbilityScheduler::SCHEDULE_ABILITY_PREPARE_TERMINATE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("end failed. err: %{public}d", err); + return false; + } + return reply.ReadBool(); +} + void AbilitySchedulerProxy::ScheduleSaveAbilityState() { MessageParcel data; diff --git a/services/abilitymgr/src/ability_scheduler_stub.cpp b/services/abilitymgr/src/ability_scheduler_stub.cpp index 49a52cb49f..84d9179c1c 100644 --- a/services/abilitymgr/src/ability_scheduler_stub.cpp +++ b/services/abilitymgr/src/ability_scheduler_stub.cpp @@ -38,6 +38,7 @@ AbilitySchedulerStub::AbilitySchedulerStub() requestFuncMap_[SCHEDULE_ABILITY_CONNECT] = &AbilitySchedulerStub::ConnectAbilityInner; requestFuncMap_[SCHEDULE_ABILITY_DISCONNECT] = &AbilitySchedulerStub::DisconnectAbilityInner; requestFuncMap_[SCHEDULE_ABILITY_COMMAND] = &AbilitySchedulerStub::CommandAbilityInner; + requestFuncMap_[SCHEDULE_ABILITY_PREPARE_TERMINATE] = &AbilitySchedulerStub::PrepareTerminateAbilityInner; requestFuncMap_[SCHEDULE_SAVE_ABILITY_STATE] = &AbilitySchedulerStub::SaveAbilityStateInner; requestFuncMap_[SCHEDULE_RESTORE_ABILITY_STATE] = &AbilitySchedulerStub::RestoreAbilityStateInner; requestFuncMap_[SCHEDULE_GETFILETYPES] = &AbilitySchedulerStub::GetFileTypesInner; @@ -171,6 +172,16 @@ int AbilitySchedulerStub::CommandAbilityInner(MessageParcel &data, MessageParcel return NO_ERROR; } +int AbilitySchedulerStub::PrepareTerminateAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + bool ret = SchedulePrepareTerminateAbility(); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("fail to write ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + int AbilitySchedulerStub::SaveAbilityStateInner(MessageParcel &data, MessageParcel &reply) { ScheduleSaveAbilityState(); diff --git a/services/abilitymgr/src/lifecycle_deal.cpp b/services/abilitymgr/src/lifecycle_deal.cpp index ba4c6f0dc8..d622ea4392 100644 --- a/services/abilitymgr/src/lifecycle_deal.cpp +++ b/services/abilitymgr/src/lifecycle_deal.cpp @@ -168,5 +168,15 @@ void LifecycleDeal::ShareData(const int32_t &uniqueId) abilityScheduler->ScheduleShareData(uniqueId); } +bool LifecycleDeal::PrepareTerminateAbility() +{ + HILOG_DEBUG("call"); + auto abilityScheduler = GetScheduler(); + if (abilityScheduler == nullptr) { + HILOG_ERROR("abilityScheduler is nullptr."); + return false; + } + return abilityScheduler->SchedulePrepareTerminateAbility(); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/prepare_terminate_callback_proxy.cpp b/services/abilitymgr/src/prepare_terminate_callback_proxy.cpp new file mode 100644 index 0000000000..98f419c94a --- /dev/null +++ b/services/abilitymgr/src/prepare_terminate_callback_proxy.cpp @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#include "ability_manager_errors.h" +#include "prepare_terminate_callback_proxy.h" +#include "hilog_wrapper.h" +#include "iremote_object.h" +#include "message_parcel.h" +#include "peer_holder.h" +#include "want_params.h" + +namespace OHOS { +namespace AAFwk { +void PrepareTerminateCallbackProxy::DoPrepareTerminate() +{ + HILOG_DEBUG("call"); + MessageParcel data; + if (!data.WriteInterfaceToken(IPrepareTerminateCallback::GetDescriptor())) { + HILOG_ERROR("Write interface token failed."); + return; + } + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("Remote() is NULL"); + return; + } + int error = remote->SendRequest(ON_DO_PREPARE_TERMINATE, data, reply, option); + if (error != ERR_OK) { + HILOG_ERROR("SendRequest fail, error: %{public}d", error); + } +} +} +} diff --git a/services/abilitymgr/src/prepare_terminate_callback_stub.cpp b/services/abilitymgr/src/prepare_terminate_callback_stub.cpp new file mode 100644 index 0000000000..a46af38e70 --- /dev/null +++ b/services/abilitymgr/src/prepare_terminate_callback_stub.cpp @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#include "prepare_terminate_callback_stub.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +PrepareTerminateCallbackStub::PrepareTerminateCallbackStub() +{ + requestFuncMap_[ON_DO_PREPARE_TERMINATE] = &PrepareTerminateCallbackStub::DoPrepareTerminateInner; +} + +PrepareTerminateCallbackStub::~PrepareTerminateCallbackStub() +{ + HILOG_INFO("call"); + requestFuncMap_.clear(); +} + +int32_t PrepareTerminateCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + if (data.ReadInterfaceToken() != IPrepareTerminateCallback::GetDescriptor()) { + HILOG_ERROR("InterfaceToken not equal IPrepareTerminateCallback's descriptor."); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t PrepareTerminateCallbackStub::DoPrepareTerminateInner(MessageParcel &data, MessageParcel &reply) +{ + HILOG_DEBUG("call"); + DoPrepareTerminate(); + return ERR_OK; +} +} +} diff --git a/test/fuzztest/abilityschedulerstub_fuzzer/abilityschedulerstub_fuzzer.cpp b/test/fuzztest/abilityschedulerstub_fuzzer/abilityschedulerstub_fuzzer.cpp index fc2651bdd6..9719cd8865 100755 --- a/test/fuzztest/abilityschedulerstub_fuzzer/abilityschedulerstub_fuzzer.cpp +++ b/test/fuzztest/abilityschedulerstub_fuzzer/abilityschedulerstub_fuzzer.cpp @@ -48,6 +48,10 @@ public: {} void ScheduleCommandAbility(const Want& want, bool restart, int startId) override {} + bool SchedulePrepareTerminateAbility() override + { + return true; + } void ScheduleSaveAbilityState() override {} void ScheduleRestoreAbilityState(const PacMap& inState) override diff --git a/test/fuzztest/attachabilitythread_fuzzer/attachabilitythread_fuzzer.cpp b/test/fuzztest/attachabilitythread_fuzzer/attachabilitythread_fuzzer.cpp index a583171439..062a67f741 100644 --- a/test/fuzztest/attachabilitythread_fuzzer/attachabilitythread_fuzzer.cpp +++ b/test/fuzztest/attachabilitythread_fuzzer/attachabilitythread_fuzzer.cpp @@ -52,6 +52,10 @@ public: {} void ScheduleCommandAbility(const Want& want, bool restart, int startId) override {} + bool SchedulePrepareTerminateAbility() override + { + return false; + } void ScheduleSaveAbilityState() override {} void ScheduleRestoreAbilityState(const PacMap& inState) override diff --git a/test/mock/frameworks_kits_ability_native_test/include/mock_ability_manager_client.h b/test/mock/frameworks_kits_ability_native_test/include/mock_ability_manager_client.h index da3f95221b..4fca6eeaa2 100644 --- a/test/mock/frameworks_kits_ability_native_test/include/mock_ability_manager_client.h +++ b/test/mock/frameworks_kits_ability_native_test/include/mock_ability_manager_client.h @@ -143,6 +143,10 @@ public: return; }; virtual void ScheduleShareData(const int32_t &uniqueId) {}; + virtual bool SchedulePrepareTerminateAbility() + { + return false; + } }; } // namespace AppExecFwk } // namespace OHOS diff --git a/test/mock/frameworks_kits_ability_native_test/include/mock_ability_scheduler_for_observer.h b/test/mock/frameworks_kits_ability_native_test/include/mock_ability_scheduler_for_observer.h index 3e1fcdf5bd..1b353956aa 100644 --- a/test/mock/frameworks_kits_ability_native_test/include/mock_ability_scheduler_for_observer.h +++ b/test/mock/frameworks_kits_ability_native_test/include/mock_ability_scheduler_for_observer.h @@ -35,6 +35,7 @@ public: MOCK_METHOD3(SendResult, void(int, int, const AAFwk::Want&)); MOCK_METHOD1(ScheduleConnectAbility, void(const AAFwk::Want&)); MOCK_METHOD1(ScheduleDisconnectAbility, void(const AAFwk::Want&)); + MOCK_METHOD0(SchedulePrepareTerminateAbility, bool()); MOCK_METHOD3(ScheduleCommandAbility, void(const AAFwk::Want&, bool, int)); MOCK_METHOD0(ScheduleSaveAbilityState, void()); MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap&)); diff --git a/test/mock/services_abilitymgr_test/libs/aakit/include/ability_scheduler.h b/test/mock/services_abilitymgr_test/libs/aakit/include/ability_scheduler.h index ef3ca5da9e..8618be25d7 100644 --- a/test/mock/services_abilitymgr_test/libs/aakit/include/ability_scheduler.h +++ b/test/mock/services_abilitymgr_test/libs/aakit/include/ability_scheduler.h @@ -43,6 +43,8 @@ public: void ScheduleDisconnectAbility(const Want& want) override; + bool SchedulePrepareTerminateAbility() override; + void ScheduleCommandAbility(const Want& want, bool restart, int startId) override; void ScheduleSaveAbilityState() override; diff --git a/test/mock/services_abilitymgr_test/libs/aakit/src/ability_scheduler.cpp b/test/mock/services_abilitymgr_test/libs/aakit/src/ability_scheduler.cpp index 41f77765dd..3c61a7ca1d 100644 --- a/test/mock/services_abilitymgr_test/libs/aakit/src/ability_scheduler.cpp +++ b/test/mock/services_abilitymgr_test/libs/aakit/src/ability_scheduler.cpp @@ -54,6 +54,11 @@ void AbilityScheduler::ScheduleConnectAbility(const Want& want) void AbilityScheduler::ScheduleDisconnectAbility(const Want& want) {} +bool AbilityScheduler::SchedulePrepareTerminateAbility() +{ + return false; +} + void AbilityScheduler::ScheduleCommandAbility(const Want& want, bool restart, int startId) {} diff --git a/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h b/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h index f17271ec55..0d86a9cabd 100644 --- a/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h +++ b/test/mock/services_abilitymgr_test/libs/ability_scheduler_mock/ability_scheduler_mock.h @@ -42,6 +42,7 @@ public: MOCK_METHOD2(ContinueAbility, void(const std::string& deviceId, uint32_t versionCode)); MOCK_METHOD2(DumpAbilityInfo, void(const std::vector& params, std::vector& info)); MOCK_METHOD1(ScheduleShareData, void(const int32_t &uniqueId)); + MOCK_METHOD0(SchedulePrepareTerminateAbility, bool()); int InvokeSendRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) { code_ = code; diff --git a/test/moduletest/mock/include/mock_ability_scheduler.h b/test/moduletest/mock/include/mock_ability_scheduler.h index 597140e13c..981748be8a 100644 --- a/test/moduletest/mock/include/mock_ability_scheduler.h +++ b/test/moduletest/mock/include/mock_ability_scheduler.h @@ -45,6 +45,7 @@ public: MOCK_METHOD1(NotifyContinuationResult, void(int32_t result)); MOCK_METHOD2(ContinueAbility, void(const std::string& deviceId, uint32_t versionCode)); MOCK_METHOD2(DumpAbilityInfo, void(const std::vector& params, std::vector& info)); + MOCK_METHOD0(SchedulePrepareTerminateAbility, bool()); std::vector GetFileTypes(const Uri& uri, const std::string& mimeTypeFilter) { std::vector types; diff --git a/test/moduletest/mock/include/mock_ability_scheduler_stub.h b/test/moduletest/mock/include/mock_ability_scheduler_stub.h index fb0efdebdf..7b42012acd 100644 --- a/test/moduletest/mock/include/mock_ability_scheduler_stub.h +++ b/test/moduletest/mock/include/mock_ability_scheduler_stub.h @@ -28,6 +28,7 @@ public: MOCK_METHOD1(ScheduleConnectAbility, void(const Want&)); MOCK_METHOD1(ScheduleDisconnectAbility, void(const Want&)); MOCK_METHOD3(ScheduleCommandAbility, void(const Want&, bool, int)); + MOCK_METHOD0(SchedulePrepareTerminateAbility, bool()); MOCK_METHOD0(ScheduleSaveAbilityState, void()); MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap&)); MOCK_METHOD2(GetFileTypes, std::vector(const Uri&, const std::string&)); diff --git a/test/unittest/ability_scheduler_stub_test/ability_schedule_stub_mock.h b/test/unittest/ability_scheduler_stub_test/ability_schedule_stub_mock.h index f831bc51c8..27110c6a32 100644 --- a/test/unittest/ability_scheduler_stub_test/ability_schedule_stub_mock.h +++ b/test/unittest/ability_scheduler_stub_test/ability_schedule_stub_mock.h @@ -36,6 +36,11 @@ public: void ScheduleDisconnectAbility(const Want& want) override {} + bool SchedulePrepareTerminateAbility() override + { + return false; + } + void ScheduleCommandAbility(const Want& want, bool restart, int startId) override {}