mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 22:21:36 -04:00
40142924a5
Signed-off-by: wangzhen <wangzhen346@huawei.com>
2977 lines
127 KiB
C++
2977 lines
127 KiB
C++
/*
|
|
* Copyright (c) 2021-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 "ability_connect_manager.h"
|
|
|
|
#include <algorithm>
|
|
#include <mutex>
|
|
#include <regex>
|
|
|
|
#include "ability_connect_callback_stub.h"
|
|
#include "ability_manager_errors.h"
|
|
#include "ability_manager_service.h"
|
|
#include "ability_resident_process_rdb.h"
|
|
#include "ability_util.h"
|
|
#include "appfreeze_manager.h"
|
|
#include "app_exit_reason_data_manager.h"
|
|
#include "app_utils.h"
|
|
#include "assert_fault_callback_death_mgr.h"
|
|
#include "extension_config.h"
|
|
#include "hitrace_meter.h"
|
|
#include "hilog_tag_wrapper.h"
|
|
#include "hilog_wrapper.h"
|
|
#include "in_process_call_wrapper.h"
|
|
#include "int_wrapper.h"
|
|
#include "parameter.h"
|
|
#include "session/host/include/zidl/session_interface.h"
|
|
#include "startup_util.h"
|
|
#include "extension_record.h"
|
|
#include "ui_extension_utils.h"
|
|
|
|
namespace OHOS {
|
|
namespace AAFwk {
|
|
namespace {
|
|
constexpr char EVENT_KEY_UID[] = "UID";
|
|
constexpr char EVENT_KEY_PID[] = "PID";
|
|
constexpr char EVENT_KEY_MESSAGE[] = "MSG";
|
|
constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
|
|
constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME";
|
|
const std::string DEBUG_APP = "debugApp";
|
|
const std::string FRS_APP_INDEX = "ohos.extra.param.key.frs_index";
|
|
const std::string FRS_BUNDLE_NAME = "com.ohos.formrenderservice";
|
|
const std::string UIEXTENSION_ABILITY_ID = "ability.want.params.uiExtensionAbilityId";
|
|
const std::string UIEXTENSION_ROOT_HOST_PID = "ability.want.params.uiExtensionRootHostPid";
|
|
const std::string MAX_UINT64_VALUE = "18446744073709551615";
|
|
const std::string IS_PRELOAD_UIEXTENSION_ABILITY = "ability.want.params.is_preload_uiextension_ability";
|
|
const std::string SEPARATOR = ":";
|
|
#ifdef SUPPORT_ASAN
|
|
const int LOAD_TIMEOUT_MULTIPLE = 150;
|
|
const int CONNECT_TIMEOUT_MULTIPLE = 45;
|
|
const int COMMAND_TIMEOUT_MULTIPLE = 75;
|
|
const int COMMAND_WINDOW_TIMEOUT_MULTIPLE = 75;
|
|
const int UI_EXTENSION_CONSUME_SESSION_TIMEOUT_MULTIPLE = 150;
|
|
#else
|
|
const int LOAD_TIMEOUT_MULTIPLE = 10;
|
|
const int CONNECT_TIMEOUT_MULTIPLE = 10;
|
|
const int COMMAND_TIMEOUT_MULTIPLE = 5;
|
|
const int COMMAND_WINDOW_TIMEOUT_MULTIPLE = 5;
|
|
const int UI_EXTENSION_CONSUME_SESSION_TIMEOUT_MULTIPLE = 10;
|
|
#endif
|
|
const int32_t AUTO_DISCONNECT_INFINITY = -1;
|
|
const std::unordered_set<std::string> FROZEN_WHITE_LIST {
|
|
"com.huawei.hmos.huaweicast"
|
|
};
|
|
constexpr char BUNDLE_NAME_DIALOG[] = "com.ohos.amsdialog";
|
|
constexpr char ABILITY_NAME_ASSERT_FAULT_DIALOG[] = "AssertFaultDialog";
|
|
constexpr char BUNDLE_NAME_SAMPLE_MANAGEMENT[] = "com.huawei.hmsapp.samplemanagement";
|
|
constexpr char ABILITY_NAME_SAMPLE_MANAGEMENT[] = "MspesService";
|
|
|
|
bool IsSpecialAbility(const AppExecFwk::AbilityInfo &abilityInfo)
|
|
{
|
|
std::vector<std::pair<std::string, std::string>> trustAbilities{
|
|
{ AbilityConfig::SCENEBOARD_BUNDLE_NAME, AbilityConfig::SCENEBOARD_ABILITY_NAME },
|
|
{ AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_ABILITY_NAME },
|
|
{ AbilityConfig::LAUNCHER_BUNDLE_NAME, AbilityConfig::LAUNCHER_ABILITY_NAME }
|
|
};
|
|
for (const auto &pair : trustAbilities) {
|
|
if (pair.first == abilityInfo.bundleName && pair.second == abilityInfo.name) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::mutex g_keepAliveAbilitiesMutex;
|
|
std::vector<std::pair<std::string, std::string>> g_keepAliveAbilities;
|
|
void GetKeepAliveAbilities()
|
|
{
|
|
if (!g_keepAliveAbilities.empty()) {
|
|
return;
|
|
}
|
|
auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
|
|
CHECK_POINTER(bundleMgrHelper);
|
|
std::vector<AppExecFwk::BundleInfo> bundleInfos;
|
|
bool getBundleInfos = bundleMgrHelper->GetBundleInfos(
|
|
OHOS::AppExecFwk::GET_BUNDLE_DEFAULT, bundleInfos, USER_ID_NO_HEAD);
|
|
if (!getBundleInfos) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Handle ability died task, get bundle infos failed.");
|
|
return;
|
|
}
|
|
|
|
auto checkIsAbilityNeedKeepAlive = [](const AppExecFwk::HapModuleInfo &hapModuleInfo,
|
|
const std::string &processName, std::string &mainElement) {
|
|
if (hapModuleInfo.isModuleJson) {
|
|
// new application model
|
|
if (hapModuleInfo.process == processName) {
|
|
mainElement = hapModuleInfo.mainElementName;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// old application model
|
|
mainElement = hapModuleInfo.mainAbility;
|
|
for (auto abilityInfo : hapModuleInfo.abilityInfos) {
|
|
if (abilityInfo.process == processName && abilityInfo.name == mainElement) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
for (const auto &bundleInfo : bundleInfos) {
|
|
std::string processName = bundleInfo.applicationInfo.process;
|
|
if (!bundleInfo.isKeepAlive || processName.empty()) {
|
|
continue;
|
|
}
|
|
std::string bundleName = bundleInfo.name;
|
|
for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
|
|
std::string mainElement;
|
|
if (checkIsAbilityNeedKeepAlive(hapModuleInfo, processName, mainElement) && !mainElement.empty()) {
|
|
g_keepAliveAbilities.emplace_back(bundleName, mainElement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool IsInKeepAliveList(const AppExecFwk::AbilityInfo &abilityInfo)
|
|
{
|
|
std::lock_guard guard(g_keepAliveAbilitiesMutex);
|
|
GetKeepAliveAbilities();
|
|
for (const auto &pair : g_keepAliveAbilities) {
|
|
if (abilityInfo.bundleName == pair.first && abilityInfo.name == pair.second) {
|
|
// Fault tolerance processing, originally returning true here
|
|
bool keepAliveEnable = true;
|
|
AmsResidentProcessRdb::GetInstance().GetResidentProcessEnable(abilityInfo.bundleName, keepAliveEnable);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s get keep alive enable: %{public}d",
|
|
abilityInfo.bundleName.c_str(), static_cast<int32_t>(keepAliveEnable));
|
|
return keepAliveEnable;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
AbilityConnectManager::AbilityConnectManager(int userId) : userId_(userId)
|
|
{
|
|
uiExtensionAbilityRecordMgr_ = std::make_unique<AbilityRuntime::ExtensionRecordManager>(userId);
|
|
}
|
|
|
|
AbilityConnectManager::~AbilityConnectManager()
|
|
{}
|
|
|
|
int AbilityConnectManager::StartAbility(const AbilityRequest &abilityRequest)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
return StartAbilityLocked(abilityRequest);
|
|
}
|
|
|
|
int AbilityConnectManager::TerminateAbility(const sptr<IRemoteObject> &token)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
return TerminateAbilityInner(token);
|
|
}
|
|
|
|
int AbilityConnectManager::TerminateAbilityInner(const sptr<IRemoteObject> &token)
|
|
{
|
|
auto abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate ability, ability is %{public}s.", element.c_str());
|
|
if (IsUIExtensionAbility(abilityRecord)) {
|
|
if (!abilityRecord->IsConnectListEmpty()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist connection, don't terminate.");
|
|
return ERR_OK;
|
|
} else if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND) ||
|
|
abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "current ability is active");
|
|
DoBackgroundAbilityWindow(abilityRecord, abilityRecord->GetSessionInfo());
|
|
MoveToTerminatingMap(abilityRecord);
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
MoveToTerminatingMap(abilityRecord);
|
|
return TerminateAbilityLocked(token);
|
|
}
|
|
|
|
int AbilityConnectManager::StopServiceAbility(const AbilityRequest &abilityRequest)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "call");
|
|
std::lock_guard guard(serialMutex_);
|
|
return StopServiceAbilityLocked(abilityRequest);
|
|
}
|
|
|
|
int AbilityConnectManager::StartAbilityLocked(const AbilityRequest &abilityRequest)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "ability_name:%{public}s", abilityRequest.want.GetElement().GetURI().c_str());
|
|
|
|
std::shared_ptr<AbilityRecord> targetService;
|
|
bool isLoadedAbility = false;
|
|
if (UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) {
|
|
auto callerAbilityRecord = AAFwk::Token::GetAbilityRecordByToken(abilityRequest.callerToken);
|
|
if (callerAbilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get callerAbilityRecord.");
|
|
return ERR_NULL_OBJECT;
|
|
}
|
|
std::string hostBundleName = callerAbilityRecord->GetAbilityInfo().bundleName;
|
|
int32_t ret = GetOrCreateExtensionRecord(abilityRequest, false, hostBundleName, targetService, isLoadedAbility);
|
|
if (ret != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get or create extension record, ret: %{public}d", ret);
|
|
return ret;
|
|
}
|
|
} else {
|
|
GetOrCreateServiceRecord(abilityRequest, false, targetService, isLoadedAbility);
|
|
}
|
|
CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Start ability: %{public}s", targetService->GetURI().c_str());
|
|
|
|
targetService->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode);
|
|
|
|
targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_START_EXTENSION);
|
|
|
|
targetService->DoBackgroundAbilityWindowDelayed(false);
|
|
|
|
if (IsUIExtensionAbility(targetService) && abilityRequest.sessionInfo && abilityRequest.sessionInfo->sessionToken) {
|
|
auto &remoteObj = abilityRequest.sessionInfo->sessionToken;
|
|
{
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
uiExtensionMap_[remoteObj] = UIExtWindowMapValType(targetService, abilityRequest.sessionInfo);
|
|
}
|
|
AddUIExtWindowDeathRecipient(remoteObj);
|
|
if (!isLoadedAbility) {
|
|
SaveUIExtRequestSessionInfo(targetService, abilityRequest.sessionInfo);
|
|
}
|
|
}
|
|
|
|
if (!isLoadedAbility) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Target service has not been loaded.");
|
|
SetLastExitReason(abilityRequest, targetService);
|
|
if (IsUIExtensionAbility(targetService)) {
|
|
targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_START_ABILITY);
|
|
}
|
|
LoadAbility(targetService);
|
|
} else if (targetService->IsAbilityState(AbilityState::ACTIVE) && !IsUIExtensionAbility(targetService)) {
|
|
// It may have been started through connect
|
|
targetService->SetWant(abilityRequest.want);
|
|
CommandAbility(targetService);
|
|
} else if (IsUIExtensionAbility(targetService)) {
|
|
DoForegroundUIExtension(targetService, abilityRequest);
|
|
} else {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service is already activating.");
|
|
EnqueueStartServiceReq(abilityRequest);
|
|
return ERR_OK;
|
|
}
|
|
|
|
sptr<Token> token = targetService->GetToken();
|
|
sptr<Token> preToken = nullptr;
|
|
if (targetService->GetPreAbilityRecord()) {
|
|
preToken = targetService->GetPreAbilityRecord()->GetToken();
|
|
}
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1);
|
|
return ERR_OK;
|
|
}
|
|
|
|
void AbilityConnectManager::SetLastExitReason(
|
|
const AbilityRequest &abilityRequest, std::shared_ptr<AbilityRecord> &targetRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
|
|
if (targetRecord == nullptr || !UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to set UIExtensionAbility last exit reason.");
|
|
return;
|
|
}
|
|
auto appExitReasonDataMgr = DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance();
|
|
if (appExitReasonDataMgr == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Get app exit reason data mgr instance is nullptr.");
|
|
return;
|
|
}
|
|
|
|
ExitReason exitReason = { REASON_UNKNOWN, "" };
|
|
const std::string keyEx = targetRecord->GetAbilityInfo().bundleName + SEPARATOR +
|
|
targetRecord->GetAbilityInfo().moduleName + SEPARATOR +
|
|
targetRecord->GetAbilityInfo().name;
|
|
if (!appExitReasonDataMgr->GetUIExtensionAbilityExitReason(keyEx, exitReason)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "There is no record of UIExtensionAbility's last exit reason in the database.");
|
|
return;
|
|
}
|
|
targetRecord->SetLastExitReason(exitReason);
|
|
}
|
|
|
|
void AbilityConnectManager::DoForegroundUIExtension(std::shared_ptr<AbilityRecord> abilityRecord,
|
|
const AbilityRequest &abilityRequest)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(abilityRequest.sessionInfo);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Foreground ability: %{public}s, persistentId: %{public}d",
|
|
abilityRecord->GetURI().c_str(), abilityRequest.sessionInfo->persistentId);
|
|
if (abilityRecord->IsReady() && !abilityRecord->IsAbilityState(AbilityState::INACTIVATING) &&
|
|
!abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING) &&
|
|
!abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING) &&
|
|
abilityRecord->IsAbilityWindowReady()) {
|
|
if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND)) {
|
|
abilityRecord->SetWant(abilityRequest.want);
|
|
CommandAbilityWindow(abilityRecord, abilityRequest.sessionInfo, WIN_CMD_FOREGROUND);
|
|
return;
|
|
} else {
|
|
if (abilityRecord->GetUIExtRequestSessionInfo() == nullptr) {
|
|
abilityRecord->SetWant(abilityRequest.want);
|
|
SaveUIExtRequestSessionInfo(abilityRecord, abilityRequest.sessionInfo);
|
|
DelayedSingleton<AppScheduler>::GetInstance()->MoveToForeground(abilityRecord->GetToken());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
EnqueueStartServiceReq(abilityRequest, abilityRecord->GetURI());
|
|
}
|
|
|
|
void AbilityConnectManager::SaveUIExtRequestSessionInfo(std::shared_ptr<AbilityRecord> abilityRecord,
|
|
sptr<SessionInfo> sessionInfo)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(taskHandler_);
|
|
abilityRecord->SetUIExtRequestSessionInfo(sessionInfo);
|
|
auto callback = [abilityRecord]() {
|
|
TAG_LOGE(
|
|
AAFwkTag::ABILITYMGR, "consume session timeout, abilityUri: %{public}s", abilityRecord->GetURI().c_str());
|
|
abilityRecord->SetUIExtRequestSessionInfo(nullptr);
|
|
};
|
|
|
|
int consumeSessionTimeout = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() *
|
|
UI_EXTENSION_CONSUME_SESSION_TIMEOUT_MULTIPLE;
|
|
std::string taskName = std::string("ConsumeSessionTimeout_") + std::to_string(abilityRecord->GetRecordId());
|
|
taskHandler_->SubmitTask(callback, taskName, consumeSessionTimeout);
|
|
}
|
|
|
|
void AbilityConnectManager::EnqueueStartServiceReq(const AbilityRequest &abilityRequest, const std::string &serviceUri)
|
|
{
|
|
std::lock_guard guard(startServiceReqListLock_);
|
|
auto abilityUri = abilityRequest.want.GetElement().GetURI();
|
|
if (!serviceUri.empty()) {
|
|
abilityUri = serviceUri;
|
|
}
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "abilityUri is %{public}s", abilityUri.c_str());
|
|
auto reqListIt = startServiceReqList_.find(abilityUri);
|
|
if (reqListIt != startServiceReqList_.end()) {
|
|
reqListIt->second->push_back(abilityRequest);
|
|
} else {
|
|
auto reqList = std::make_shared<std::list<AbilityRequest>>();
|
|
reqList->push_back(abilityRequest);
|
|
startServiceReqList_.emplace(abilityUri, reqList);
|
|
|
|
CHECK_POINTER(taskHandler_);
|
|
auto callback = [abilityUri, connectManager = shared_from_this()]() {
|
|
std::lock_guard guard{connectManager->startServiceReqListLock_};
|
|
auto exist = connectManager->startServiceReqList_.erase(abilityUri);
|
|
if (exist) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Target service %{public}s start timeout", abilityUri.c_str());
|
|
}
|
|
};
|
|
|
|
int connectTimeout =
|
|
AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * CONNECT_TIMEOUT_MULTIPLE;
|
|
taskHandler_->SubmitTask(callback, std::string("start_service_timeout:") + abilityUri,
|
|
connectTimeout);
|
|
}
|
|
}
|
|
|
|
int AbilityConnectManager::TerminateAbilityLocked(const sptr<IRemoteObject> &token)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
|
|
auto abilityRecord = GetExtensionByTokenFromTerminatingMap(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
|
|
if (abilityRecord->IsTerminating()) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability is on terminating.");
|
|
return ERR_OK;
|
|
}
|
|
|
|
if (!abilityRecord->GetConnectRecordList().empty()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service has been connected. Post disconnect task.");
|
|
auto connectRecordList = abilityRecord->GetConnectRecordList();
|
|
HandleTerminateDisconnectTask(connectRecordList);
|
|
}
|
|
|
|
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Disconnect ability terminate timeout.");
|
|
connectManager->HandleStopTimeoutTask(abilityRecord);
|
|
};
|
|
abilityRecord->Terminate(timeoutTask);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
AddUIExtensionAbilityRecordToTerminatedList(abilityRecord);
|
|
} else {
|
|
RemoveUIExtensionAbilityRecord(abilityRecord);
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::StopServiceAbilityLocked(const AbilityRequest &abilityRequest)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "call");
|
|
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, GenerateBundleName(abilityRequest),
|
|
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
|
|
auto abilityRecord = GetServiceRecordByElementName(element.GetURI());
|
|
if (FRS_BUNDLE_NAME == abilityRequest.abilityInfo.bundleName) {
|
|
abilityRecord = GetServiceRecordByElementName(
|
|
element.GetURI() + std::to_string(abilityRequest.want.GetIntParam(FRS_APP_INDEX, 0)));
|
|
}
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
|
|
if (abilityRecord->IsTerminating()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability is on terminating.");
|
|
return ERR_OK;
|
|
}
|
|
|
|
if (!abilityRecord->GetConnectRecordList().empty()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Post disconnect task.");
|
|
auto connectRecordList = abilityRecord->GetConnectRecordList();
|
|
HandleTerminateDisconnectTask(connectRecordList);
|
|
}
|
|
|
|
TerminateRecord(abilityRecord);
|
|
EventInfo eventInfo = BuildEventInfo(abilityRecord);
|
|
EventReport::SendStopServiceEvent(EventName::STOP_SERVICE, eventInfo);
|
|
return ERR_OK;
|
|
}
|
|
|
|
int32_t AbilityConnectManager::GetOrCreateExtensionRecord(const AbilityRequest &abilityRequest, bool isCreatedByConnect,
|
|
const std::string &hostBundleName, std::shared_ptr<AbilityRecord> &extensionRecord, bool &isLoaded)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName,
|
|
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
|
|
if (uiExtensionAbilityRecordMgr_->IsBelongToManager(abilityRequest.abilityInfo)) {
|
|
int32_t ret = uiExtensionAbilityRecordMgr_->GetOrCreateExtensionRecord(
|
|
abilityRequest, hostBundleName, extensionRecord, isLoaded);
|
|
if (ret != ERR_OK) {
|
|
return ret;
|
|
}
|
|
extensionRecord->SetCreateByConnectMode(isCreatedByConnect);
|
|
std::string extensionRecordKey = element.GetURI() + std::to_string(extensionRecord->GetUIExtensionAbilityId());
|
|
extensionRecord->SetURI(extensionRecordKey);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Service map add, hostBundleName:%{public}s, key: %{public}s",
|
|
hostBundleName.c_str(), extensionRecordKey.c_str());
|
|
AddToServiceMap(extensionRecordKey, extensionRecord);
|
|
if (IsAbilityNeedKeepAlive(extensionRecord)) {
|
|
extensionRecord->SetRestartTime(abilityRequest.restartTime);
|
|
extensionRecord->SetRestartCount(abilityRequest.restartCount);
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
return ERR_INVALID_VALUE;
|
|
}
|
|
|
|
void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abilityRequest,
|
|
const bool isCreatedByConnect, std::shared_ptr<AbilityRecord> &targetService, bool &isLoadedAbility)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
// lifecycle is not complete when window extension is reused
|
|
bool noReuse = UIExtensionUtils::IsWindowExtension(abilityRequest.abilityInfo.extensionAbilityType);
|
|
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, GenerateBundleName(abilityRequest),
|
|
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
|
|
std::string serviceKey = element.GetURI();
|
|
if (FRS_BUNDLE_NAME == abilityRequest.abilityInfo.bundleName) {
|
|
serviceKey = element.GetURI() + std::to_string(abilityRequest.want.GetIntParam(FRS_APP_INDEX, 0));
|
|
}
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto serviceMapIter = serviceMap_.find(serviceKey);
|
|
targetService = serviceMapIter == serviceMap_.end() ? nullptr : serviceMapIter->second;
|
|
}
|
|
if (noReuse && targetService) {
|
|
if (IsSpecialAbility(abilityRequest.abilityInfo)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Removing ability: %{public}s", element.GetURI().c_str());
|
|
}
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
serviceMap_.erase(serviceKey);
|
|
}
|
|
if (noReuse || targetService == nullptr) {
|
|
targetService = AbilityRecord::CreateAbilityRecord(abilityRequest);
|
|
if (targetService) {
|
|
targetService->SetOwnerMissionUserId(userId_);
|
|
}
|
|
|
|
if (isCreatedByConnect && targetService != nullptr) {
|
|
targetService->SetCreateByConnectMode();
|
|
}
|
|
if (targetService && abilityRequest.abilityInfo.name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
|
|
targetService->SetLauncherRoot();
|
|
targetService->SetRestartTime(abilityRequest.restartTime);
|
|
targetService->SetRestartCount(abilityRequest.restartCount);
|
|
} else if (IsAbilityNeedKeepAlive(targetService)) {
|
|
targetService->SetRestartTime(abilityRequest.restartTime);
|
|
targetService->SetRestartCount(abilityRequest.restartCount);
|
|
}
|
|
AddToServiceMap(serviceKey, targetService);
|
|
isLoadedAbility = false;
|
|
} else {
|
|
isLoadedAbility = true;
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::GetConnectRecordListFromMap(
|
|
const sptr<IAbilityConnection> &connect, std::list<std::shared_ptr<ConnectionRecord>> &connectRecordList)
|
|
{
|
|
std::lock_guard lock(connectMapMutex_);
|
|
auto connectMapIter = connectMap_.find(connect->AsObject());
|
|
if (connectMapIter != connectMap_.end()) {
|
|
connectRecordList = connectMapIter->second;
|
|
}
|
|
}
|
|
|
|
int32_t AbilityConnectManager::GetOrCreateTargetServiceRecord(
|
|
const AbilityRequest &abilityRequest, const sptr<UIExtensionAbilityConnectInfo> &connectInfo,
|
|
std::shared_ptr<AbilityRecord> &targetService, bool &isLoadedAbility)
|
|
{
|
|
if (UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType) && connectInfo != nullptr) {
|
|
int32_t ret = GetOrCreateExtensionRecord(
|
|
abilityRequest, true, connectInfo->hostBundleName, targetService, isLoadedAbility);
|
|
if (ret != ERR_OK || targetService == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get or create extension record.");
|
|
return ERR_NULL_OBJECT;
|
|
}
|
|
connectInfo->uiExtensionAbilityId = targetService->GetUIExtensionAbilityId();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "UIExtensionAbility id %{public}d.", connectInfo->uiExtensionAbilityId);
|
|
} else {
|
|
GetOrCreateServiceRecord(abilityRequest, true, targetService, isLoadedAbility);
|
|
}
|
|
CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE);
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::PreloadUIExtensionAbilityLocked(const AbilityRequest &abilityRequest,
|
|
std::string &hostBundleName)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
return PreloadUIExtensionAbilityInner(abilityRequest, hostBundleName);
|
|
}
|
|
|
|
int AbilityConnectManager::PreloadUIExtensionAbilityInner(const AbilityRequest &abilityRequest,
|
|
std::string &hostBundleName)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
if (!UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't preload non-uiextension type.");
|
|
return ERR_WRONG_INTERFACE_CALL;
|
|
}
|
|
std::shared_ptr<ExtensionRecord> extensionRecord = nullptr;
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
|
|
int32_t extensionRecordId = INVALID_EXTENSION_RECORD_ID;
|
|
int32_t ret = uiExtensionAbilityRecordMgr_->CreateExtensionRecord(abilityRequest, hostBundleName,
|
|
extensionRecord, extensionRecordId);
|
|
if (ret != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "CreateExtensionRecord ERR.");
|
|
return ret;
|
|
}
|
|
CHECK_POINTER_AND_RETURN(extensionRecord, ERR_NULL_OBJECT);
|
|
std::shared_ptr<AbilityRecord> targetService = extensionRecord->abilityRecord_;
|
|
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName,
|
|
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
|
|
std::string extensionRecordKey = element.GetURI() + std::to_string(targetService->GetUIExtensionAbilityId());
|
|
targetService->SetURI(extensionRecordKey);
|
|
AddToServiceMap(extensionRecordKey, targetService);
|
|
LoadAbility(targetService);
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::UnloadUIExtensionAbility(const std::shared_ptr<AAFwk::AbilityRecord> &abilityRecord,
|
|
std::string &hostBundleName)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
//Get preLoadUIExtensionInfo
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
auto preLoadUIExtensionInfo = std::make_tuple(abilityRecord->GetWant().GetElement().GetAbilityName(),
|
|
abilityRecord->GetWant().GetElement().GetBundleName(),
|
|
abilityRecord->GetWant().GetElement().GetModuleName(), hostBundleName);
|
|
//delete preLoadUIExtensionMap
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
|
|
uiExtensionAbilityRecordMgr_->RemoveAllPreloadUIExtensionRecord(preLoadUIExtensionInfo);
|
|
//terminate preload uiextension
|
|
auto token = abilityRecord->GetToken();
|
|
auto result = TerminateAbilityInner(token);
|
|
if (result != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "terminate error!");
|
|
return result;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::ConnectAbilityLocked(const AbilityRequest &abilityRequest,
|
|
const sptr<IAbilityConnection> &connect, const sptr<IRemoteObject> &callerToken, sptr<SessionInfo> sessionInfo,
|
|
sptr<UIExtensionAbilityConnectInfo> connectInfo)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER_AND_RETURN(connect, ERR_INVALID_VALUE);
|
|
auto connectObject = connect->AsObject();
|
|
std::lock_guard guard(serialMutex_);
|
|
|
|
// 1. get target service ability record, and check whether it has been loaded.
|
|
std::shared_ptr<AbilityRecord> targetService;
|
|
bool isLoadedAbility = false;
|
|
int32_t ret = GetOrCreateTargetServiceRecord(abilityRequest, connectInfo, targetService, isLoadedAbility);
|
|
if (ret != ERR_OK) {
|
|
return ret;
|
|
}
|
|
// 2. get target connectRecordList, and check whether this callback has been connected.
|
|
ConnectListType connectRecordList;
|
|
GetConnectRecordListFromMap(connect, connectRecordList);
|
|
bool isCallbackConnected = !connectRecordList.empty();
|
|
// 3. If this service ability and callback has been connected, There is no need to connect repeatedly
|
|
if (isLoadedAbility && (isCallbackConnected) && IsAbilityConnected(targetService, connectRecordList)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Service and callback was connected.");
|
|
return ERR_OK;
|
|
}
|
|
|
|
// 4. Other cases , need to connect the service ability
|
|
auto connectRecord = ConnectionRecord::CreateConnectionRecord(callerToken, targetService, connect);
|
|
CHECK_POINTER_AND_RETURN(connectRecord, ERR_INVALID_VALUE);
|
|
connectRecord->AttachCallerInfo();
|
|
connectRecord->SetConnectState(ConnectionState::CONNECTING);
|
|
targetService->AddConnectRecordToList(connectRecord);
|
|
targetService->SetSessionInfo(sessionInfo);
|
|
connectRecordList.push_back(connectRecord);
|
|
AddConnectObjectToMap(connectObject, connectRecordList, isCallbackConnected);
|
|
targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_CONNECT_EXTENSION);
|
|
|
|
if (UIExtensionUtils::IsWindowExtension(targetService->GetAbilityInfo().extensionAbilityType)
|
|
&& abilityRequest.sessionInfo) {
|
|
std::lock_guard guard(windowExtensionMapMutex_);
|
|
windowExtensionMap_.emplace(connectObject,
|
|
WindowExtMapValType(targetService->GetApplicationInfo().accessTokenId, abilityRequest.sessionInfo));
|
|
}
|
|
|
|
if (!isLoadedAbility) {
|
|
LoadAbility(targetService);
|
|
} else if (targetService->IsAbilityState(AbilityState::ACTIVE)) {
|
|
targetService->SetWant(abilityRequest.want);
|
|
HandleActiveAbility(targetService, connectRecord);
|
|
} else {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Target service is activating, wait for callback");
|
|
}
|
|
|
|
auto token = targetService->GetToken();
|
|
auto preToken = iface_cast<Token>(connectRecord->GetToken());
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1);
|
|
return ret;
|
|
}
|
|
|
|
void AbilityConnectManager::HandleActiveAbility(std::shared_ptr<AbilityRecord> &targetService,
|
|
std::shared_ptr<ConnectionRecord> &connectRecord)
|
|
{
|
|
if (targetService == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "null target service.");
|
|
return;
|
|
}
|
|
if (targetService->GetConnectRecordList().size() > 1) {
|
|
if (taskHandler_ != nullptr && targetService->GetConnRemoteObject()) {
|
|
auto task = [connectRecord]() { connectRecord->CompleteConnect(ERR_OK); };
|
|
taskHandler_->SubmitTask(task, TaskQoS::USER_INTERACTIVE);
|
|
} else {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service is connecting, wait for callback");
|
|
}
|
|
} else {
|
|
ConnectAbility(targetService);
|
|
}
|
|
}
|
|
|
|
int AbilityConnectManager::DisconnectAbilityLocked(const sptr<IAbilityConnection> &connect)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
return DisconnectAbilityLocked(connect, false);
|
|
}
|
|
|
|
int AbilityConnectManager::DisconnectAbilityLocked(const sptr<IAbilityConnection> &connect, bool force)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
|
|
// 1. check whether callback was connected.
|
|
ConnectListType connectRecordList;
|
|
GetConnectRecordListFromMap(connect, connectRecordList);
|
|
if (connectRecordList.empty()) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't find the connect list from connect map by callback.");
|
|
return CONNECTION_NOT_EXIST;
|
|
}
|
|
|
|
// 2. schedule disconnect to target service
|
|
int result = ERR_OK;
|
|
ConnectListType list;
|
|
for (auto &connectRecord : connectRecordList) {
|
|
if (connectRecord) {
|
|
auto abilityRecord = connectRecord->GetAbilityRecord();
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "abilityName: %{public}s, bundleName: %{public}s",
|
|
abilityRecord->GetAbilityInfo().name.c_str(), abilityRecord->GetAbilityInfo().bundleName.c_str());
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::EXTENSION) {
|
|
RemoveExtensionDelayDisconnectTask(connectRecord);
|
|
}
|
|
if (connectRecord->GetCallerTokenId() != IPCSkeleton::GetCallingTokenID() &&
|
|
static_cast<uint32_t>(IPCSkeleton::GetSelfTokenID() != IPCSkeleton::GetCallingTokenID())) {
|
|
TAG_LOGW(
|
|
AAFwkTag::ABILITYMGR, "The caller is inconsistent with the caller stored in the connectRecord.");
|
|
continue;
|
|
}
|
|
|
|
result = DisconnectRecordNormal(list, connectRecord);
|
|
if (result != ERR_OK && force) {
|
|
DisconnectRecordForce(list, connectRecord);
|
|
result = ERR_OK;
|
|
}
|
|
|
|
if (result != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect ability fail , ret = %{public}d.", result);
|
|
break;
|
|
} else {
|
|
EventInfo eventInfo = BuildEventInfo(abilityRecord);
|
|
EventReport::SendDisconnectServiceEvent(EventName::DISCONNECT_SERVICE, eventInfo);
|
|
}
|
|
}
|
|
}
|
|
for (auto&& connectRecord : list) {
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void AbilityConnectManager::TerminateRecord(std::shared_ptr<AbilityRecord> abilityRecord)
|
|
{
|
|
if (!GetAbilityRecordById(abilityRecord->GetRecordId())) {
|
|
return;
|
|
}
|
|
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Disconnect ability terminate timeout.");
|
|
connectManager->HandleStopTimeoutTask(abilityRecord);
|
|
};
|
|
|
|
MoveToTerminatingMap(abilityRecord);
|
|
abilityRecord->Terminate(timeoutTask);
|
|
}
|
|
|
|
int AbilityConnectManager::DisconnectRecordNormal(ConnectListType &list,
|
|
std::shared_ptr<ConnectionRecord> connectRecord) const
|
|
{
|
|
auto result = connectRecord->DisconnectAbility();
|
|
if (result != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect ability fail , ret = %{public}d.", result);
|
|
return result;
|
|
}
|
|
|
|
if (connectRecord->GetConnectState() == ConnectionState::DISCONNECTED) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "This record: %{public}d complete disconnect directly.",
|
|
connectRecord->GetRecordId());
|
|
connectRecord->CompleteDisconnect(ERR_OK, false);
|
|
list.emplace_back(connectRecord);
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
void AbilityConnectManager::DisconnectRecordForce(ConnectListType &list,
|
|
std::shared_ptr<ConnectionRecord> connectRecord)
|
|
{
|
|
auto abilityRecord = connectRecord->GetAbilityRecord();
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect force abilityRecord null");
|
|
return;
|
|
}
|
|
abilityRecord->RemoveConnectRecordFromList(connectRecord);
|
|
connectRecord->CompleteDisconnect(ERR_OK, true);
|
|
list.emplace_back(connectRecord);
|
|
if (abilityRecord->IsConnectListEmpty() && abilityRecord->GetStartId() == 0) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Force terminate ability record state: %{public}d.",
|
|
abilityRecord->GetAbilityState());
|
|
TerminateRecord(abilityRecord);
|
|
}
|
|
}
|
|
|
|
int AbilityConnectManager::AttachAbilityThreadLocked(
|
|
const sptr<IAbilityScheduler> &scheduler, const sptr<IRemoteObject> &token)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
auto abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
if (abilityRecord == nullptr) {
|
|
abilityRecord = GetExtensionByTokenFromTerminatingMap(token);
|
|
if (abilityRecord != nullptr && !IsUIExtensionAbility(abilityRecord)) {
|
|
abilityRecord = nullptr;
|
|
}
|
|
}
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability: %{public}s", element.c_str());
|
|
if (taskHandler_ != nullptr) {
|
|
int recordId = abilityRecord->GetRecordId();
|
|
std::string taskName = std::string("LoadTimeout_") + std::to_string(recordId);
|
|
taskHandler_->CancelTask(taskName);
|
|
}
|
|
if (eventHandler_) {
|
|
eventHandler_->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG,
|
|
abilityRecord->GetAbilityRecordId());
|
|
}
|
|
if (abilityRecord->IsSceneBoard()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Attach Ability: %{public}s", element.c_str());
|
|
sceneBoardTokenId_ = abilityRecord->GetAbilityInfo().applicationInfo.accessTokenId;
|
|
}
|
|
abilityRecord->SetScheduler(scheduler);
|
|
abilityRecord->RemoveSpecifiedWantParam(UIEXTENSION_ABILITY_ID);
|
|
abilityRecord->RemoveSpecifiedWantParam(UIEXTENSION_ROOT_HOST_PID);
|
|
if (IsUIExtensionAbility(abilityRecord) && !abilityRecord->IsCreateByConnect()
|
|
&& !abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->MoveToForeground(token);
|
|
} else {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Inactivate");
|
|
abilityRecord->Inactivate();
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
void AbilityConnectManager::OnAbilityRequestDone(const sptr<IRemoteObject> &token, const int32_t state)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "state: %{public}d", state);
|
|
std::lock_guard guard(serialMutex_);
|
|
AppAbilityState abilityState = DelayedSingleton<AppScheduler>::GetInstance()->ConvertToAppAbilityState(state);
|
|
if (abilityState == AppAbilityState::ABILITY_STATE_FOREGROUND) {
|
|
auto abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
CHECK_POINTER(abilityRecord);
|
|
if (!IsUIExtensionAbility(abilityRecord)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Not ui extension.");
|
|
return;
|
|
}
|
|
if (abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "abilityRecord is foregrounding.");
|
|
return;
|
|
}
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability is %{public}s, start to foreground.", element.c_str());
|
|
MoveToForeground(abilityRecord);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::OnAppStateChanged(const AppInfo &info)
|
|
{
|
|
auto serviceMap = GetServiceMap();
|
|
std::for_each(serviceMap.begin(), serviceMap.end(), [&info](ServiceMapType::reference service) {
|
|
if (service.second && (info.processName == service.second->GetAbilityInfo().process ||
|
|
info.processName == service.second->GetApplicationInfo().bundleName)) {
|
|
auto appName = service.second->GetApplicationInfo().name;
|
|
auto uid = service.second->GetAbilityInfo().applicationInfo.uid;
|
|
auto isExist = [&appName, &uid](
|
|
const AppData &appData) { return appData.appName == appName && appData.uid == uid; };
|
|
auto iter = std::find_if(info.appData.begin(), info.appData.end(), isExist);
|
|
if (iter != info.appData.end()) {
|
|
service.second->SetAppState(info.state);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
int AbilityConnectManager::AbilityTransitionDone(const sptr<IRemoteObject> &token, int state)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast<AbilityLifeCycleState>(state));
|
|
std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast<AbilityState>(targetState));
|
|
std::shared_ptr<AbilityRecord> abilityRecord;
|
|
if (targetState == AbilityState::INACTIVE) {
|
|
abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
} else if (targetState == AbilityState::FOREGROUND || targetState == AbilityState::BACKGROUND) {
|
|
abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
if (abilityRecord == nullptr) {
|
|
abilityRecord = GetExtensionByTokenFromTerminatingMap(token);
|
|
}
|
|
} else if (targetState == AbilityState::INITIAL) {
|
|
abilityRecord = GetExtensionByTokenFromTerminatingMap(token);
|
|
} else {
|
|
abilityRecord = nullptr;
|
|
}
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability: %{public}s, state: %{public}s", element.c_str(), abilityState.c_str());
|
|
|
|
switch (targetState) {
|
|
case AbilityState::INACTIVE: {
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateAbilityState(
|
|
token, AppExecFwk::AbilityState::ABILITY_STATE_CREATE);
|
|
} else {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateExtensionState(
|
|
token, AppExecFwk::ExtensionState::EXTENSION_STATE_CREATE);
|
|
auto preloadTask = [owner = weak_from_this(), abilityRecord] {
|
|
auto acm = owner.lock();
|
|
if (acm == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "AbilityConnectManager is nullptr.");
|
|
return;
|
|
}
|
|
acm->ProcessPreload(abilityRecord);
|
|
};
|
|
if (taskHandler_ != nullptr) {
|
|
taskHandler_->SubmitTask(preloadTask);
|
|
}
|
|
}
|
|
return DispatchInactive(abilityRecord, state);
|
|
}
|
|
case AbilityState::FOREGROUND: {
|
|
return DispatchForeground(abilityRecord);
|
|
}
|
|
case AbilityState::BACKGROUND: {
|
|
return DispatchBackground(abilityRecord);
|
|
}
|
|
case AbilityState::INITIAL: {
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateAbilityState(
|
|
token, AppExecFwk::AbilityState::ABILITY_STATE_TERMINATED);
|
|
} else {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateExtensionState(
|
|
token, AppExecFwk::ExtensionState::EXTENSION_STATE_TERMINATED);
|
|
}
|
|
return DispatchTerminate(abilityRecord);
|
|
}
|
|
default: {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Don't support transiting state: %{public}d", state);
|
|
return ERR_INVALID_VALUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::ProcessPreload(const std::shared_ptr<AbilityRecord> &record) const
|
|
{
|
|
auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
|
|
CHECK_POINTER(bundleMgrHelper);
|
|
auto abilityInfo = record->GetAbilityInfo();
|
|
Want want;
|
|
want.SetElementName(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name, abilityInfo.moduleName);
|
|
auto uid = record->GetUid();
|
|
want.SetParam("uid", uid);
|
|
bundleMgrHelper->ProcessPreload(want);
|
|
}
|
|
|
|
int AbilityConnectManager::ScheduleConnectAbilityDoneLocked(
|
|
const sptr<IRemoteObject> &token, const sptr<IRemoteObject> &remoteObject)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE);
|
|
|
|
auto abilityRecord = Token::GetAbilityRecordByToken(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Connect ability done, ability: %{public}s.", element.c_str());
|
|
|
|
if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) &&
|
|
(!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability record state is not inactive ,state: %{public}d",
|
|
abilityRecord->GetAbilityState());
|
|
return INVALID_CONNECTION_STATE;
|
|
}
|
|
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateAbilityState(
|
|
token, AppExecFwk::AbilityState::ABILITY_STATE_CONNECTED);
|
|
} else {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateExtensionState(
|
|
token, AppExecFwk::ExtensionState::EXTENSION_STATE_CONNECTED);
|
|
}
|
|
EventInfo eventInfo = BuildEventInfo(abilityRecord);
|
|
eventInfo.userId = userId_;
|
|
eventInfo.bundleName = abilityRecord->GetAbilityInfo().bundleName;
|
|
eventInfo.moduleName = abilityRecord->GetAbilityInfo().moduleName;
|
|
eventInfo.abilityName = abilityRecord->GetAbilityInfo().name;
|
|
EventReport::SendConnectServiceEvent(EventName::CONNECT_SERVICE, eventInfo);
|
|
|
|
abilityRecord->SetConnRemoteObject(remoteObject);
|
|
// There may be multiple callers waiting for the connection result
|
|
auto connectRecordList = abilityRecord->GetConnectRecordList();
|
|
for (auto &connectRecord : connectRecordList) {
|
|
connectRecord->ScheduleConnectAbilityDone();
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::EXTENSION &&
|
|
abilityRecord->GetAbilityInfo().extensionAbilityType != AppExecFwk::ExtensionAbilityType::SERVICE) {
|
|
PostExtensionDelayDisconnectTask(connectRecord);
|
|
}
|
|
}
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::ScheduleDisconnectAbilityDoneLocked(const sptr<IRemoteObject> &token)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
auto abilityRecord = GetExtensionByTokenFromServiceMap(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, CONNECTION_NOT_EXIST);
|
|
|
|
auto connect = abilityRecord->GetDisconnectingRecord();
|
|
CHECK_POINTER_AND_RETURN(connect, CONNECTION_NOT_EXIST);
|
|
|
|
if (!abilityRecord->IsAbilityState(AbilityState::ACTIVE)) {
|
|
if (IsUIExtensionAbility(abilityRecord) && (abilityRecord->IsForeground() ||
|
|
abilityRecord->IsAbilityState(AbilityState::BACKGROUND) ||
|
|
abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING))) {
|
|
// uiextension ability support connect and start, so the ability state maybe others
|
|
TAG_LOGI(
|
|
AAFwkTag::ABILITYMGR, "Disconnect when ability state is %{public}d", abilityRecord->GetAbilityState());
|
|
} else {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "The service ability state is not active ,state: %{public}d",
|
|
abilityRecord->GetAbilityState());
|
|
return INVALID_CONNECTION_STATE;
|
|
}
|
|
}
|
|
|
|
if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateAbilityState(
|
|
token, AppExecFwk::AbilityState::ABILITY_STATE_DISCONNECTED);
|
|
} else {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->UpdateExtensionState(
|
|
token, AppExecFwk::ExtensionState::EXTENSION_STATE_DISCONNECTED);
|
|
}
|
|
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Disconnect ability done, service:%{public}s.", element.c_str());
|
|
|
|
// complete disconnect and remove record from conn map
|
|
connect->ScheduleDisconnectAbilityDone();
|
|
abilityRecord->RemoveConnectRecordFromList(connect);
|
|
if (abilityRecord->IsConnectListEmpty() && abilityRecord->GetStartId() == 0) {
|
|
if (IsUIExtensionAbility(abilityRecord) && CheckUIExtensionAbilitySessionExist(abilityRecord)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist ui extension component, don't terminate when disconnect.");
|
|
} else {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Service ability has no any connection, and not started, need terminate.");
|
|
RemoveUIExtensionAbilityRecord(abilityRecord);
|
|
if (!abilityRecord->IsSceneBoard()) {
|
|
TerminateRecord(abilityRecord);
|
|
}
|
|
}
|
|
}
|
|
RemoveConnectionRecordFromMap(connect);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::ScheduleCommandAbilityDoneLocked(const sptr<IRemoteObject> &token)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE);
|
|
auto abilityRecord = Token::GetAbilityRecordByToken(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability: %{public}s", element.c_str());
|
|
|
|
if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) &&
|
|
(!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability record state is not inactive ,state: %{public}d",
|
|
abilityRecord->GetAbilityState());
|
|
return INVALID_CONNECTION_STATE;
|
|
}
|
|
EventInfo eventInfo = BuildEventInfo(abilityRecord);
|
|
EventReport::SendStartServiceEvent(EventName::START_SERVICE, eventInfo);
|
|
// complete command and pop waiting start ability from queue.
|
|
CompleteCommandAbility(abilityRecord);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::ScheduleCommandAbilityWindowDone(
|
|
const sptr<IRemoteObject> &token,
|
|
const sptr<SessionInfo> &sessionInfo,
|
|
WindowCommand winCmd,
|
|
AbilityCommand abilityCmd)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE);
|
|
CHECK_POINTER_AND_RETURN(sessionInfo, ERR_INVALID_VALUE);
|
|
auto abilityRecord = Token::GetAbilityRecordByToken(token);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
std::string element = abilityRecord->GetURI();
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR,
|
|
"Ability: %{public}s, persistentId: %{private}d, winCmd: %{public}d, abilityCmd: %{public}d", element.c_str(),
|
|
sessionInfo->persistentId, winCmd, abilityCmd);
|
|
|
|
// Only foreground mode need cancel, cause only foreground CommandAbilityWindow post timeout task.
|
|
if (taskHandler_ && winCmd == WIN_CMD_FOREGROUND) {
|
|
int recordId = abilityRecord->GetRecordId();
|
|
std::string taskName = std::string("CommandWindowTimeout_") + std::to_string(recordId) + std::string("_") +
|
|
std::to_string(sessionInfo->persistentId) + std::string("_") + std::to_string(winCmd);
|
|
taskHandler_->CancelTask(taskName);
|
|
}
|
|
|
|
if (winCmd == WIN_CMD_DESTROY) {
|
|
HandleCommandDestroy(sessionInfo);
|
|
}
|
|
|
|
abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, true);
|
|
|
|
CompleteStartServiceReq(element);
|
|
return ERR_OK;
|
|
}
|
|
|
|
void AbilityConnectManager::HandleCommandDestroy(const sptr<SessionInfo> &sessionInfo)
|
|
{
|
|
if (sessionInfo == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "null session info.");
|
|
return;
|
|
}
|
|
if (sessionInfo->sessionToken) {
|
|
RemoveUIExtWindowDeathRecipient(sessionInfo->sessionToken);
|
|
size_t ret = 0;
|
|
{
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
ret = uiExtensionMap_.erase(sessionInfo->sessionToken);
|
|
}
|
|
if (ret > 0) {
|
|
return;
|
|
}
|
|
|
|
std::lock_guard guard(windowExtensionMapMutex_);
|
|
for (auto& item : windowExtensionMap_) {
|
|
auto sessionInfoVal = item.second.second;
|
|
if (sessionInfoVal && sessionInfoVal->callerToken == sessionInfo->sessionToken) {
|
|
windowExtensionMap_.erase(item.first);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::CompleteCommandAbility(std::shared_ptr<AbilityRecord> abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
if (taskHandler_) {
|
|
int recordId = abilityRecord->GetRecordId();
|
|
std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") +
|
|
std::to_string(abilityRecord->GetStartId());
|
|
taskHandler_->CancelTask(taskName);
|
|
}
|
|
|
|
abilityRecord->SetAbilityState(AbilityState::ACTIVE);
|
|
|
|
// manage queued request
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
if (abilityRecord->NeedConnectAfterCommand()) {
|
|
ConnectAbility(abilityRecord);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::CompleteStartServiceReq(const std::string &serviceUri)
|
|
{
|
|
std::shared_ptr<std::list<OHOS::AAFwk::AbilityRequest>> reqList;
|
|
{
|
|
std::lock_guard guard(startServiceReqListLock_);
|
|
auto it = startServiceReqList_.find(serviceUri);
|
|
if (it != startServiceReqList_.end()) {
|
|
reqList = it->second;
|
|
startServiceReqList_.erase(it);
|
|
if (taskHandler_) {
|
|
taskHandler_->CancelTask(std::string("start_service_timeout:") + serviceUri);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (reqList) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service is activating : %{public}zu, uri: %{public}s", reqList->size(),
|
|
serviceUri.c_str());
|
|
for (const auto &req: *reqList) {
|
|
StartAbilityLocked(req);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetServiceRecordByElementName(const std::string &element)
|
|
{
|
|
std::lock_guard guard(serviceMapMutex_);
|
|
auto mapIter = serviceMap_.find(element);
|
|
if (mapIter != serviceMap_.end()) {
|
|
return mapIter->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetExtensionByTokenFromServiceMap(
|
|
const sptr<IRemoteObject> &token)
|
|
{
|
|
auto IsMatch = [token](auto service) {
|
|
if (!service.second) {
|
|
return false;
|
|
}
|
|
sptr<IRemoteObject> srcToken = service.second->GetToken();
|
|
return srcToken == token;
|
|
};
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch);
|
|
if (serviceRecord != serviceMap_.end()) {
|
|
return serviceRecord->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetExtensionByIdFromServiceMap(
|
|
int32_t abilityRecordId)
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (const auto &[key, value] : serviceMap_) {
|
|
if (value && value->GetAbilityRecordId() == abilityRecordId) {
|
|
return value;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetUIExtensioBySessionInfo(
|
|
const sptr<SessionInfo> &sessionInfo)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(sessionInfo, nullptr);
|
|
auto sessionToken = iface_cast<Rosen::ISession>(sessionInfo->sessionToken);
|
|
CHECK_POINTER_AND_RETURN(sessionToken, nullptr);
|
|
std::string descriptor = Str16ToStr8(sessionToken->GetDescriptor());
|
|
if (descriptor != "OHOS.ISession") {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Input token is not a sessionToken, token->GetDescriptor(): %{public}s",
|
|
descriptor.c_str());
|
|
return nullptr;
|
|
}
|
|
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
auto it = uiExtensionMap_.find(sessionToken->AsObject());
|
|
if (it != uiExtensionMap_.end()) {
|
|
auto abilityRecord = it->second.first.lock();
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr.");
|
|
RemoveUIExtWindowDeathRecipient(sessionToken->AsObject());
|
|
uiExtensionMap_.erase(it);
|
|
return nullptr;
|
|
}
|
|
auto savedSessionInfo = it->second.second;
|
|
if (!savedSessionInfo || savedSessionInfo->sessionToken != sessionInfo->sessionToken
|
|
|| savedSessionInfo->callerToken != sessionInfo->callerToken) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Inconsistent sessionInfo.");
|
|
return nullptr;
|
|
}
|
|
return abilityRecord;
|
|
} else {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "UIExtension not found.");
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetExtensionByTokenFromTerminatingMap(
|
|
const sptr<IRemoteObject> &token)
|
|
{
|
|
auto IsMatch = [token](auto& extension) {
|
|
if (extension.second == nullptr) {
|
|
return false;
|
|
}
|
|
auto terminatingToken = extension.second->GetToken();
|
|
if (terminatingToken != nullptr) {
|
|
return terminatingToken->AsObject() == token;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto terminatingExtensionRecord =
|
|
std::find_if(terminatingExtensionMap_.begin(), terminatingExtensionMap_.end(), IsMatch);
|
|
if (terminatingExtensionRecord != terminatingExtensionMap_.end()) {
|
|
return terminatingExtensionRecord->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::list<std::shared_ptr<ConnectionRecord>> AbilityConnectManager::GetConnectRecordListByCallback(
|
|
sptr<IAbilityConnection> callback)
|
|
{
|
|
std::lock_guard guard(connectMapMutex_);
|
|
std::list<std::shared_ptr<ConnectionRecord>> connectList;
|
|
auto connectMapIter = connectMap_.find(callback->AsObject());
|
|
if (connectMapIter != connectMap_.end()) {
|
|
connectList = connectMapIter->second;
|
|
}
|
|
return connectList;
|
|
}
|
|
|
|
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetAbilityRecordById(int64_t abilityRecordId)
|
|
{
|
|
auto IsMatch = [abilityRecordId](auto service) {
|
|
if (!service.second) {
|
|
return false;
|
|
}
|
|
return abilityRecordId == service.second->GetAbilityRecordId();
|
|
};
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch);
|
|
if (serviceRecord != serviceMap_.end()) {
|
|
return serviceRecord->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void AbilityConnectManager::LoadAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER(abilityRecord);
|
|
abilityRecord->SetStartTime();
|
|
|
|
if (!abilityRecord->CanRestartRootLauncher()) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Root launcher restart is out of max count.");
|
|
RemoveServiceAbility(abilityRecord);
|
|
return;
|
|
}
|
|
if (!abilityRecord->IsDebugApp()) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "IsDebug is false, here is not debug app");
|
|
PostTimeOutTask(abilityRecord, AbilityManagerService::LOAD_TIMEOUT_MSG);
|
|
}
|
|
sptr<Token> token = abilityRecord->GetToken();
|
|
sptr<Token> perToken = nullptr;
|
|
if (abilityRecord->IsCreateByConnect()) {
|
|
perToken = iface_cast<Token>(abilityRecord->GetConnectingRecord()->GetToken());
|
|
} else {
|
|
auto callerList = abilityRecord->GetCallerRecordList();
|
|
if (!callerList.empty() && callerList.back()) {
|
|
auto caller = callerList.back()->GetCaller();
|
|
if (caller) {
|
|
perToken = caller->GetToken();
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateUIExtensionInfo(abilityRecord);
|
|
DelayedSingleton<AppScheduler>::GetInstance()->LoadAbility(
|
|
token, perToken, abilityRecord->GetAbilityInfo(), abilityRecord->GetApplicationInfo(),
|
|
abilityRecord->GetWant(), abilityRecord->GetRecordId());
|
|
}
|
|
|
|
void AbilityConnectManager::PostRestartResidentTask(const AbilityRequest &abilityRequest)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "PostRestartResidentTask start.");
|
|
CHECK_POINTER(taskHandler_);
|
|
std::string taskName = std::string("RestartResident_") + std::string(abilityRequest.abilityInfo.name);
|
|
auto task = [abilityRequest, connectManager = shared_from_this()]() {
|
|
CHECK_POINTER(connectManager);
|
|
connectManager->HandleRestartResidentTask(abilityRequest);
|
|
};
|
|
int restartIntervalTime = 0;
|
|
auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
|
|
if (abilityMgr) {
|
|
restartIntervalTime = AmsConfigurationParameter::GetInstance().GetRestartIntervalTime();
|
|
}
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "PostRestartResidentTask, time:%{public}d", restartIntervalTime);
|
|
taskHandler_->SubmitTask(task, taskName, restartIntervalTime);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "PostRestartResidentTask end.");
|
|
}
|
|
|
|
void AbilityConnectManager::HandleRestartResidentTask(const AbilityRequest &abilityRequest)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleRestartResidentTask start.");
|
|
std::lock_guard guard(serialMutex_);
|
|
auto findRestartResidentTask = [abilityRequest](const AbilityRequest &requestInfo) {
|
|
return (requestInfo.want.GetElement().GetBundleName() == abilityRequest.want.GetElement().GetBundleName() &&
|
|
requestInfo.want.GetElement().GetModuleName() == abilityRequest.want.GetElement().GetModuleName() &&
|
|
requestInfo.want.GetElement().GetAbilityName() == abilityRequest.want.GetElement().GetAbilityName());
|
|
};
|
|
auto findIter = find_if(restartResidentTaskList_.begin(), restartResidentTaskList_.end(), findRestartResidentTask);
|
|
if (findIter != restartResidentTaskList_.end()) {
|
|
restartResidentTaskList_.erase(findIter);
|
|
}
|
|
StartAbilityLocked(abilityRequest);
|
|
}
|
|
|
|
void AbilityConnectManager::PostTimeOutTask(const std::shared_ptr<AbilityRecord> &abilityRecord, uint32_t messageId)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(taskHandler_);
|
|
|
|
std::string taskName;
|
|
int32_t delayTime = 0;
|
|
if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) {
|
|
// first load ability, There is at most one connect record.
|
|
int recordId = abilityRecord->GetRecordId();
|
|
taskName = std::string("LoadTimeout_") + std::to_string(recordId);
|
|
delayTime = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * LOAD_TIMEOUT_MULTIPLE;
|
|
} else if (messageId == AbilityConnectManager::CONNECT_TIMEOUT_MSG) {
|
|
auto connectRecord = abilityRecord->GetConnectingRecord();
|
|
CHECK_POINTER(connectRecord);
|
|
int recordId = connectRecord->GetRecordId();
|
|
taskName = std::string("ConnectTimeout_") + std::to_string(recordId);
|
|
delayTime = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * CONNECT_TIMEOUT_MULTIPLE;
|
|
} else {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Timeout task messageId is error.");
|
|
return;
|
|
}
|
|
|
|
// check libc.hook_mode
|
|
const int bufferLen = 128;
|
|
char paramOutBuf[bufferLen] = {0};
|
|
const char *hook_mode = "startup:";
|
|
int ret = GetParameter("libc.hook_mode", "", paramOutBuf, bufferLen - 1);
|
|
if (ret > 0 && strncmp(paramOutBuf, hook_mode, strlen(hook_mode)) == 0) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Hook_mode: no timeoutTask");
|
|
return;
|
|
}
|
|
|
|
auto timeoutTask = [abilityRecord, connectManager = shared_from_this(), messageId]() {
|
|
if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) {
|
|
connectManager->HandleStartTimeoutTask(abilityRecord);
|
|
} else if (messageId == AbilityConnectManager::CONNECT_TIMEOUT_MSG) {
|
|
connectManager->HandleConnectTimeoutTask(abilityRecord);
|
|
}
|
|
};
|
|
taskHandler_->SubmitTask(timeoutTask, taskName, delayTime);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleStartTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "load ability timeout.");
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER(abilityRecord);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
if (uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Start load timeout.");
|
|
uiExtensionAbilityRecordMgr_->LoadTimeout(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
PrintTimeOutLog(abilityRecord, AbilityManagerService::LOAD_TIMEOUT_MSG);
|
|
}
|
|
auto connectingList = abilityRecord->GetConnectingRecordList();
|
|
for (auto &connectRecord : connectingList) {
|
|
if (connectRecord == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "ConnectRecord is nullptr.");
|
|
continue;
|
|
}
|
|
connectRecord->CompleteDisconnect(ERR_OK, false, true);
|
|
abilityRecord->RemoveConnectRecordFromList(connectRecord);
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
}
|
|
|
|
if (GetExtensionByTokenFromServiceMap(abilityRecord->GetToken()) == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Timeout ability record is not exist in service map.");
|
|
return;
|
|
}
|
|
MoveToTerminatingMap(abilityRecord);
|
|
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Load time out , remove target service record from services map.");
|
|
RemoveServiceAbility(abilityRecord);
|
|
if (abilityRecord->GetAbilityInfo().name != AbilityConfig::LAUNCHER_ABILITY_NAME) {
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(abilityRecord->GetToken());
|
|
if (IsAbilityNeedKeepAlive(abilityRecord)) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Load time out , try to restart.");
|
|
RestartAbility(abilityRecord, userId_);
|
|
}
|
|
} else {
|
|
// terminate the timeout root launcher.
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(abilityRecord->GetToken());
|
|
StartRootLauncher(abilityRecord);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::HandleCommandTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
if (abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Handle root launcher command timeout.");
|
|
// terminate the timeout root launcher.
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(abilityRecord->GetToken());
|
|
}
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleCommandTimeoutTask end");
|
|
}
|
|
|
|
void AbilityConnectManager::HandleConnectTimeoutTask(std::shared_ptr<AbilityRecord> abilityRecord)
|
|
{
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "connect ability timeout.");
|
|
CHECK_POINTER(abilityRecord);
|
|
auto connectList = abilityRecord->GetConnectRecordList();
|
|
std::lock_guard guard(serialMutex_);
|
|
for (const auto &connectRecord : connectList) {
|
|
RemoveExtensionDelayDisconnectTask(connectRecord);
|
|
connectRecord->CompleteDisconnect(ERR_OK, false, true);
|
|
abilityRecord->RemoveConnectRecordFromList(connectRecord);
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
}
|
|
|
|
if (IsSpecialAbility(abilityRecord->GetAbilityInfo()) || abilityRecord->GetStartId() != 0) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "no need to terminate.");
|
|
return;
|
|
}
|
|
|
|
TerminateRecord(abilityRecord);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleCommandWindowTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const sptr<SessionInfo> &sessionInfo, WindowCommand winCmd)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "start");
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER(abilityRecord);
|
|
abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, true);
|
|
// manage queued request
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "end");
|
|
}
|
|
|
|
void AbilityConnectManager::StartRootLauncher(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
AbilityRequest requestInfo;
|
|
requestInfo.want = abilityRecord->GetWant();
|
|
requestInfo.abilityInfo = abilityRecord->GetAbilityInfo();
|
|
requestInfo.appInfo = abilityRecord->GetApplicationInfo();
|
|
requestInfo.restartTime = abilityRecord->GetRestartTime();
|
|
requestInfo.restart = true;
|
|
requestInfo.restartCount = abilityRecord->GetRestartCount() - 1;
|
|
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "restart root launcher, number:%{public}d", requestInfo.restartCount);
|
|
StartAbilityLocked(requestInfo);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleStopTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Complete stop ability timeout start.");
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER(abilityRecord);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
if (uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Start terminate timeout.");
|
|
uiExtensionAbilityRecordMgr_->TerminateTimeout(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
PrintTimeOutLog(abilityRecord, AbilityManagerService::TERMINATE_TIMEOUT_MSG);
|
|
}
|
|
TerminateDone(abilityRecord);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleTerminateDisconnectTask(const ConnectListType& connectlist)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Disconnect ability when terminate.");
|
|
for (auto& connectRecord : connectlist) {
|
|
if (!connectRecord) {
|
|
continue;
|
|
}
|
|
auto targetService = connectRecord->GetAbilityRecord();
|
|
if (targetService) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "This record complete disconnect directly. recordId:%{public}d",
|
|
connectRecord->GetRecordId());
|
|
connectRecord->CompleteDisconnect(ERR_OK, false, true);
|
|
targetService->RemoveConnectRecordFromList(connectRecord);
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
};
|
|
}
|
|
}
|
|
|
|
int AbilityConnectManager::DispatchInactive(const std::shared_ptr<AbilityRecord> &abilityRecord, int state)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "DispatchInactive call");
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
CHECK_POINTER_AND_RETURN(eventHandler_, ERR_INVALID_VALUE);
|
|
if (!abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR,
|
|
"Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d",
|
|
AbilityState::INACTIVATING, abilityRecord->GetAbilityState(), state);
|
|
return ERR_INVALID_VALUE;
|
|
}
|
|
eventHandler_->RemoveEvent(AbilityManagerService::INACTIVE_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId());
|
|
|
|
// complete inactive
|
|
abilityRecord->SetAbilityState(AbilityState::INACTIVE);
|
|
if (abilityRecord->IsCreateByConnect()) {
|
|
ConnectAbility(abilityRecord);
|
|
} else if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "IS_PRELOAD_UIEXTENSION_ABILITY");
|
|
auto ret = uiExtensionAbilityRecordMgr_->AddPreloadUIExtensionRecord(abilityRecord);
|
|
if (ret != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Add preload UI Extension record error!");
|
|
return ret;
|
|
}
|
|
return ERR_OK;
|
|
} else {
|
|
CommandAbility(abilityRecord);
|
|
if (abilityRecord->GetConnectRecordList().size() > 0) {
|
|
// It means someone called connectAbility when service was loading
|
|
ConnectAbility(abilityRecord);
|
|
}
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::DispatchForeground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
CHECK_POINTER_AND_RETURN(taskHandler_, ERR_INVALID_VALUE);
|
|
// remove foreground timeout task.
|
|
taskHandler_->CancelTask("foreground_" + std::to_string(abilityRecord->GetAbilityRecordId()));
|
|
|
|
auto self(shared_from_this());
|
|
auto task = [self, abilityRecord]() { self->CompleteForeground(abilityRecord); };
|
|
taskHandler_->SubmitTask(task, TaskQoS::USER_INTERACTIVE);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::DispatchBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
CHECK_POINTER_AND_RETURN(taskHandler_, ERR_INVALID_VALUE);
|
|
// remove background timeout task.
|
|
taskHandler_->CancelTask("background_" + std::to_string(abilityRecord->GetAbilityRecordId()));
|
|
|
|
auto self(shared_from_this());
|
|
auto task = [self, abilityRecord]() { self->CompleteBackground(abilityRecord); };
|
|
taskHandler_->SubmitTask(task, TaskQoS::USER_INTERACTIVE);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
int AbilityConnectManager::DispatchTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
|
// remove terminate timeout task
|
|
if (taskHandler_ != nullptr) {
|
|
taskHandler_->CancelTask("terminate_" + std::to_string(abilityRecord->GetAbilityRecordId()));
|
|
}
|
|
// complete terminate
|
|
TerminateDone(abilityRecord);
|
|
return ERR_OK;
|
|
}
|
|
|
|
void AbilityConnectManager::ConnectAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER(abilityRecord);
|
|
PostTimeOutTask(abilityRecord, AbilityConnectManager::CONNECT_TIMEOUT_MSG);
|
|
abilityRecord->ConnectAbility();
|
|
}
|
|
|
|
void AbilityConnectManager::CommandAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
if (taskHandler_ != nullptr) {
|
|
// first connect ability, There is at most one connect record.
|
|
int recordId = abilityRecord->GetRecordId();
|
|
abilityRecord->AddStartId();
|
|
std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") +
|
|
std::to_string(abilityRecord->GetStartId());
|
|
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Command ability timeout. %{public}s",
|
|
abilityRecord->GetAbilityInfo().name.c_str());
|
|
connectManager->HandleCommandTimeoutTask(abilityRecord);
|
|
};
|
|
int commandTimeout =
|
|
AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * COMMAND_TIMEOUT_MULTIPLE;
|
|
taskHandler_->SubmitTask(timeoutTask, taskName, commandTimeout);
|
|
// scheduling command ability
|
|
abilityRecord->CommandAbility();
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::CommandAbilityWindow(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const sptr<SessionInfo> &sessionInfo, WindowCommand winCmd)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(sessionInfo);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "ability: %{public}s, persistentId: %{private}d, wincmd: %{public}d",
|
|
abilityRecord->GetURI().c_str(), sessionInfo->persistentId, winCmd);
|
|
abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, false);
|
|
if (taskHandler_ != nullptr) {
|
|
int recordId = abilityRecord->GetRecordId();
|
|
std::string taskName = std::string("CommandWindowTimeout_") + std::to_string(recordId) + std::string("_") +
|
|
std::to_string(sessionInfo->persistentId) + std::string("_") + std::to_string(winCmd);
|
|
auto timeoutTask = [abilityRecord, sessionInfo, winCmd, connectManager = shared_from_this()]() {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Command window timeout. %{public}s",
|
|
abilityRecord->GetAbilityInfo().name.c_str());
|
|
connectManager->HandleCommandWindowTimeoutTask(abilityRecord, sessionInfo, winCmd);
|
|
};
|
|
int commandWindowTimeout =
|
|
AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * COMMAND_WINDOW_TIMEOUT_MULTIPLE;
|
|
taskHandler_->SubmitTask(timeoutTask, taskName, commandWindowTimeout);
|
|
// scheduling command ability
|
|
abilityRecord->CommandAbilityWindow(sessionInfo, winCmd);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::BackgroundAbilityWindowLocked(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const sptr<SessionInfo> &sessionInfo)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
DoBackgroundAbilityWindow(abilityRecord, sessionInfo);
|
|
}
|
|
|
|
void AbilityConnectManager::DoBackgroundAbilityWindow(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const sptr<SessionInfo> &sessionInfo)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(sessionInfo);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Background ability: %{public}s, persistentId: %{public}d",
|
|
abilityRecord->GetURI().c_str(), sessionInfo->persistentId);
|
|
|
|
if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND)) {
|
|
MoveToBackground(abilityRecord);
|
|
} else if (abilityRecord->IsAbilityState(AbilityState::INITIAL) ||
|
|
abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist initial or foregrounding task.");
|
|
abilityRecord->DoBackgroundAbilityWindowDelayed(true);
|
|
} else {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid ability state when background.");
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::TerminateAbilityWindowLocked(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const sptr<SessionInfo> &sessionInfo)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(sessionInfo);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Terminate ability: %{public}s, persistentId: %{public}d",
|
|
abilityRecord->GetURI().c_str(), sessionInfo->persistentId);
|
|
EventInfo eventInfo;
|
|
eventInfo.bundleName = abilityRecord->GetAbilityInfo().bundleName;
|
|
eventInfo.abilityName = abilityRecord->GetAbilityInfo().name;
|
|
EventReport::SendAbilityEvent(EventName::TERMINATE_ABILITY, HiSysEventType::BEHAVIOR, eventInfo);
|
|
std::lock_guard guard(serialMutex_);
|
|
eventInfo.errCode = TerminateAbilityInner(abilityRecord->GetToken());
|
|
if (eventInfo.errCode != ERR_OK) {
|
|
EventReport::SendAbilityEvent(EventName::TERMINATE_ABILITY_ERROR, HiSysEventType::FAULT, eventInfo);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::TerminateDone(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER(abilityRecord);
|
|
if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) {
|
|
std::string expect = AbilityRecord::ConvertAbilityState(AbilityState::TERMINATING);
|
|
std::string actual = AbilityRecord::ConvertAbilityState(abilityRecord->GetAbilityState());
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR,
|
|
"Transition life state error. expect %{public}s, actual %{public}s", expect.c_str(), actual.c_str());
|
|
return;
|
|
}
|
|
IN_PROCESS_CALL_WITHOUT_RET(abilityRecord->RevokeUriPermission());
|
|
abilityRecord->RemoveAbilityDeathRecipient();
|
|
if (abilityRecord->IsSceneBoard()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "To kill processes because scb exit.");
|
|
KillProcessesByUserId();
|
|
}
|
|
DelayedSingleton<AppScheduler>::GetInstance()->TerminateAbility(abilityRecord->GetToken(), false);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
RemoveUIExtensionAbilityRecord(abilityRecord);
|
|
}
|
|
RemoveServiceAbility(abilityRecord);
|
|
}
|
|
|
|
bool AbilityConnectManager::IsAbilityConnected(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const std::list<std::shared_ptr<ConnectionRecord>> &connectRecordList)
|
|
{
|
|
auto isMatch = [abilityRecord](auto connectRecord) -> bool {
|
|
if (abilityRecord == nullptr || connectRecord == nullptr) {
|
|
return false;
|
|
}
|
|
if (abilityRecord != connectRecord->GetAbilityRecord()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
return std::any_of(connectRecordList.begin(), connectRecordList.end(), isMatch);
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveConnectionRecordFromMap(std::shared_ptr<ConnectionRecord> connection)
|
|
{
|
|
std::lock_guard lock(connectMapMutex_);
|
|
for (auto &connectCallback : connectMap_) {
|
|
auto &connectList = connectCallback.second;
|
|
auto connectRecord = std::find(connectList.begin(), connectList.end(), connection);
|
|
if (connectRecord != connectList.end()) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "connrecord(%{public}d)", (*connectRecord)->GetRecordId());
|
|
connectList.remove(connection);
|
|
if (connectList.empty()) {
|
|
RemoveConnectDeathRecipient(connectCallback.first);
|
|
connectMap_.erase(connectCallback.first);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveServiceAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Remove service(%{public}s) from terminating map.", abilityRecord->GetURI().c_str());
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
terminatingExtensionMap_.erase(abilityRecord->GetURI());
|
|
}
|
|
|
|
void AbilityConnectManager::AddConnectDeathRecipient(sptr<IRemoteObject> connectObject)
|
|
{
|
|
CHECK_POINTER(connectObject);
|
|
{
|
|
std::lock_guard guard(recipientMapMutex_);
|
|
auto it = recipientMap_.find(connectObject);
|
|
if (it != recipientMap_.end()) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "This death recipient has been added.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::weak_ptr<AbilityConnectManager> thisWeakPtr(shared_from_this());
|
|
sptr<IRemoteObject::DeathRecipient> deathRecipient =
|
|
new AbilityConnectCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
|
|
auto abilityConnectManager = thisWeakPtr.lock();
|
|
if (abilityConnectManager) {
|
|
abilityConnectManager->OnCallBackDied(remote);
|
|
}
|
|
});
|
|
if (!connectObject->AddDeathRecipient(deathRecipient)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "AddDeathRecipient failed.");
|
|
return;
|
|
}
|
|
std::lock_guard guard(recipientMapMutex_);
|
|
recipientMap_.emplace(connectObject, deathRecipient);
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveConnectDeathRecipient(sptr<IRemoteObject> connectObject)
|
|
{
|
|
CHECK_POINTER(connectObject);
|
|
sptr<IRemoteObject::DeathRecipient> deathRecipient;
|
|
{
|
|
std::lock_guard guard(recipientMapMutex_);
|
|
auto it = recipientMap_.find(connectObject);
|
|
if (it == recipientMap_.end()) {
|
|
return;
|
|
}
|
|
deathRecipient = it->second;
|
|
recipientMap_.erase(it);
|
|
}
|
|
|
|
connectObject->RemoveDeathRecipient(deathRecipient);
|
|
}
|
|
|
|
void AbilityConnectManager::OnCallBackDied(const wptr<IRemoteObject> &remote)
|
|
{
|
|
auto object = remote.promote();
|
|
CHECK_POINTER(object);
|
|
if (taskHandler_) {
|
|
auto task = [object, connectManager = shared_from_this()]() { connectManager->HandleCallBackDiedTask(object); };
|
|
taskHandler_->SubmitTask(task, TASK_ON_CALLBACK_DIED);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::HandleCallBackDiedTask(const sptr<IRemoteObject> &connect)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
|
|
CHECK_POINTER(connect);
|
|
{
|
|
std::lock_guard guard(windowExtensionMapMutex_);
|
|
auto item = windowExtensionMap_.find(connect);
|
|
if (item != windowExtensionMap_.end()) {
|
|
windowExtensionMap_.erase(item);
|
|
}
|
|
}
|
|
|
|
{
|
|
std::lock_guard guard(connectMapMutex_);
|
|
auto it = connectMap_.find(connect);
|
|
if (it != connectMap_.end()) {
|
|
ConnectListType connectRecordList = it->second;
|
|
for (auto &connRecord : connectRecordList) {
|
|
connRecord->ClearConnCallBack();
|
|
}
|
|
} else {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Died object can't find from conn map.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
sptr<IAbilityConnection> object = iface_cast<IAbilityConnection>(connect);
|
|
std::lock_guard guard(serialMutex_);
|
|
DisconnectAbilityLocked(object, true);
|
|
}
|
|
|
|
int32_t AbilityConnectManager::GetActiveUIExtensionList(
|
|
const int32_t pid, std::vector<std::string> &extensionList)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
|
|
return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionList(pid, extensionList);
|
|
}
|
|
|
|
int32_t AbilityConnectManager::GetActiveUIExtensionList(
|
|
const std::string &bundleName, std::vector<std::string> &extensionList)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT);
|
|
return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionList(bundleName, extensionList);
|
|
}
|
|
|
|
void AbilityConnectManager::OnAbilityDied(const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "On ability died: %{public}s.", abilityRecord->GetURI().c_str());
|
|
if (abilityRecord->GetAbilityInfo().type != AbilityType::SERVICE &&
|
|
abilityRecord->GetAbilityInfo().type != AbilityType::EXTENSION) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Ability type is not service.");
|
|
return;
|
|
}
|
|
if (taskHandler_) {
|
|
auto task = [abilityRecord, connectManager = shared_from_this(), currentUserId]() {
|
|
connectManager->HandleAbilityDiedTask(abilityRecord, currentUserId);
|
|
};
|
|
taskHandler_->SubmitTask(task, TASK_ON_ABILITY_DIED);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId)
|
|
{
|
|
auto abilityRecord = GetAbilityRecordById(abilityRecordId);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "AbilityConnectManager on time out event: ability record is nullptr.");
|
|
return;
|
|
}
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability timeout ,msg:%{public}d,name:%{public}s", msgId,
|
|
abilityRecord->GetAbilityInfo().name.c_str());
|
|
|
|
switch (msgId) {
|
|
case AbilityManagerService::INACTIVE_TIMEOUT_MSG:
|
|
HandleInactiveTimeout(abilityRecord);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::HandleInactiveTimeout(const std::shared_ptr<AbilityRecord> &ability)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleInactiveTimeout start");
|
|
CHECK_POINTER(ability);
|
|
if (ability->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Handle root launcher inactive timeout.");
|
|
// terminate the timeout root launcher.
|
|
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(ability->GetToken());
|
|
}
|
|
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleInactiveTimeout end");
|
|
}
|
|
|
|
bool AbilityConnectManager::IsAbilityNeedKeepAlive(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, false);
|
|
const auto &abilityInfo = abilityRecord->GetAbilityInfo();
|
|
if (IsSpecialAbility(abilityInfo)) {
|
|
return true;
|
|
}
|
|
|
|
if (IsInKeepAliveList(abilityInfo)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void AbilityConnectManager::ClearPreloadUIExtensionRecord(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called.");
|
|
CHECK_POINTER(abilityRecord);
|
|
auto extensionRecordId = abilityRecord->GetUIExtensionAbilityId();
|
|
std::string hostBundleName;
|
|
auto ret = uiExtensionAbilityRecordMgr_->GetHostBundleNameForExtensionId(extensionRecordId, hostBundleName);
|
|
if (ret != ERR_OK) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "cannot get hostbundlename for this extension id.");
|
|
return;
|
|
}
|
|
auto extensionRecordMapKey = std::make_tuple(abilityRecord->GetWant().GetElement().GetAbilityName(),
|
|
abilityRecord->GetWant().GetElement().GetBundleName(),
|
|
abilityRecord->GetWant().GetElement().GetModuleName(), hostBundleName);
|
|
uiExtensionAbilityRecordMgr_->RemovePreloadUIExtensionRecordById(extensionRecordMapKey, extensionRecordId);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleAbilityDiedTask(
|
|
const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called.");
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER(abilityRecord);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability died: %{public}s", abilityRecord->GetURI().c_str());
|
|
abilityRecord->SetConnRemoteObject(nullptr);
|
|
ConnectListType connlist = abilityRecord->GetConnectRecordList();
|
|
for (auto &connectRecord : connlist) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "This record complete disconnect directly. recordId:%{public}d",
|
|
connectRecord->GetRecordId());
|
|
RemoveExtensionDelayDisconnectTask(connectRecord);
|
|
connectRecord->CompleteDisconnect(ERR_OK, false, true);
|
|
abilityRecord->RemoveConnectRecordFromList(connectRecord);
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
}
|
|
if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) {
|
|
ClearPreloadUIExtensionRecord(abilityRecord);
|
|
}
|
|
if (IsUIExtensionAbility(abilityRecord)) {
|
|
HandleUIExtensionDied(abilityRecord);
|
|
}
|
|
|
|
auto token = abilityRecord->GetToken();
|
|
bool isRemove = false;
|
|
if (GetExtensionByIdFromServiceMap(abilityRecord->GetAbilityRecordId()) != nullptr) {
|
|
MoveToTerminatingMap(abilityRecord);
|
|
RemoveServiceAbility(abilityRecord);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
RemoveUIExtensionAbilityRecord(abilityRecord);
|
|
}
|
|
isRemove = true;
|
|
}
|
|
|
|
if (IsAbilityNeedKeepAlive(abilityRecord)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "restart ability: %{public}s", abilityRecord->GetAbilityInfo().name.c_str());
|
|
if ((IsLauncher(abilityRecord) || abilityRecord->IsSceneBoard()) && token != nullptr) {
|
|
IN_PROCESS_CALL_WITHOUT_RET(DelayedSingleton<AppScheduler>::GetInstance()->ClearProcessByToken(
|
|
token->AsObject()));
|
|
}
|
|
if (abilityRecord->IsSceneBoard() && currentUserId != userId_) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Not the current user's SCB, clear the user and do not restart");
|
|
KillProcessesByUserId();
|
|
return;
|
|
}
|
|
if (DelayedSingleton<AppScheduler>::GetInstance()->IsMemorySizeSufficent() ||
|
|
IsLauncher(abilityRecord) || abilityRecord->IsSceneBoard() || IsSampleManagement(abilityRecord)) {
|
|
RestartAbility(abilityRecord, currentUserId);
|
|
}
|
|
} else {
|
|
if (isRemove) {
|
|
HandleNotifyAssertFaultDialogDied(abilityRecord);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool CheckIsNumString(const std::string &numStr)
|
|
{
|
|
const std::regex regexJsperf(R"(^\d*)");
|
|
std::match_results<std::string::const_iterator> matchResults;
|
|
if (numStr.empty() || !std::regex_match(numStr, matchResults, regexJsperf)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Number parsing error, %{public}s.", numStr.c_str());
|
|
return false;
|
|
}
|
|
if (MAX_UINT64_VALUE.length() < numStr.length() ||
|
|
(MAX_UINT64_VALUE.length() == numStr.length() && MAX_UINT64_VALUE.compare(numStr) < 0)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Number parsing error, %{public}s.", numStr.c_str());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AbilityConnectManager::HandleNotifyAssertFaultDialogDied(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Called.");
|
|
CHECK_POINTER(abilityRecord);
|
|
if (abilityRecord->GetAbilityInfo().name != ABILITY_NAME_ASSERT_FAULT_DIALOG ||
|
|
abilityRecord->GetAbilityInfo().bundleName != BUNDLE_NAME_DIALOG) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Is not assert fault dialog.");
|
|
return;
|
|
}
|
|
|
|
auto want = abilityRecord->GetWant();
|
|
auto assertSessionStr = want.GetStringParam(Want::PARAM_ASSERT_FAULT_SESSION_ID);
|
|
if (!CheckIsNumString(assertSessionStr)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Check assert session str is number failed.");
|
|
return;
|
|
}
|
|
|
|
auto callbackDeathMgr = DelayedSingleton<AbilityRuntime::AssertFaultCallbackDeathMgr>::GetInstance();
|
|
if (callbackDeathMgr == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Get callback death manager instance is nullptr.");
|
|
return;
|
|
}
|
|
callbackDeathMgr->CallAssertFaultCallback(std::stoull(assertSessionStr));
|
|
}
|
|
|
|
void AbilityConnectManager::CloseAssertDialog(const std::string &assertSessionId)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Called");
|
|
sptr<IRemoteObject> token;
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (const auto &item : serviceMap_) {
|
|
if (item.second == nullptr) {
|
|
continue;
|
|
}
|
|
|
|
auto assertSessionStr = item.second->GetWant().GetStringParam(Want::PARAM_ASSERT_FAULT_SESSION_ID);
|
|
if (assertSessionStr == assertSessionId) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate assert fault dialog called.");
|
|
terminatingExtensionMap_.emplace(item.first, item.second);
|
|
token = item.second->GetToken();
|
|
serviceMap_.erase(item.first);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (token != nullptr) {
|
|
std::lock_guard lock(serialMutex_);
|
|
TerminateAbilityLocked(token);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::HandleUIExtensionDied(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
|
|
CHECK_POINTER(abilityRecord);
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
for (auto it = uiExtensionMap_.begin(); it != uiExtensionMap_.end();) {
|
|
std::shared_ptr<AbilityRecord> uiExtAbility = it->second.first.lock();
|
|
if (uiExtAbility == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "uiExtAbility is nullptr");
|
|
RemoveUIExtWindowDeathRecipient(it->first);
|
|
it = uiExtensionMap_.erase(it);
|
|
continue;
|
|
}
|
|
|
|
if (abilityRecord == uiExtAbility) {
|
|
sptr<Rosen::ISession> sessionProxy = iface_cast<Rosen::ISession>(it->first);
|
|
if (sessionProxy) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "start NotifyExtensionDied");
|
|
sessionProxy->NotifyExtensionDied();
|
|
}
|
|
RemoveUIExtWindowDeathRecipient(it->first);
|
|
it = uiExtensionMap_.erase(it);
|
|
continue;
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::RestartAbility(const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Restart ability: %{public}s.", abilityRecord->GetURI().c_str());
|
|
AbilityRequest requestInfo;
|
|
requestInfo.want = abilityRecord->GetWant();
|
|
requestInfo.abilityInfo = abilityRecord->GetAbilityInfo();
|
|
requestInfo.appInfo = abilityRecord->GetApplicationInfo();
|
|
requestInfo.restartTime = abilityRecord->GetRestartTime();
|
|
requestInfo.restart = true;
|
|
abilityRecord->SetRestarting(true);
|
|
|
|
if (AppUtils::GetInstance().IsLauncherAbility(abilityRecord->GetAbilityInfo().name)) {
|
|
if (currentUserId != userId_) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "delay restart root launcher until switch user.");
|
|
return;
|
|
}
|
|
requestInfo.want.SetParam("ohos.app.recovery", true);
|
|
requestInfo.restartCount = abilityRecord->GetRestartCount();
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "restart root launcher, number:%{public}d", requestInfo.restartCount);
|
|
StartAbilityLocked(requestInfo);
|
|
return;
|
|
}
|
|
|
|
// restart other resident ability
|
|
if (abilityRecord->CanRestartResident()) {
|
|
requestInfo.restartCount = abilityRecord->GetRestartCount();
|
|
requestInfo.restartTime = AbilityUtil::SystemTimeMillis();
|
|
StartAbilityLocked(requestInfo);
|
|
} else {
|
|
auto findRestartResidentTask = [requestInfo](const AbilityRequest &abilityRequest) {
|
|
return (requestInfo.want.GetElement().GetBundleName() == abilityRequest.want.GetElement().GetBundleName() &&
|
|
requestInfo.want.GetElement().GetModuleName() == abilityRequest.want.GetElement().GetModuleName() &&
|
|
requestInfo.want.GetElement().GetAbilityName() == abilityRequest.want.GetElement().GetAbilityName());
|
|
};
|
|
auto findIter = find_if(restartResidentTaskList_.begin(), restartResidentTaskList_.end(),
|
|
findRestartResidentTask);
|
|
if (findIter != restartResidentTaskList_.end()) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "The restart task has been registered.");
|
|
return;
|
|
}
|
|
restartResidentTaskList_.emplace_back(requestInfo);
|
|
PostRestartResidentTask(requestInfo);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::DumpState(std::vector<std::string> &info, bool isClient, const std::string &args)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "args:%{public}s.", args.c_str());
|
|
auto serviceMapBack = GetServiceMap();
|
|
if (!args.empty()) {
|
|
auto it = std::find_if(serviceMapBack.begin(), serviceMapBack.end(), [&args](const auto &service) {
|
|
return service.first.compare(args) == 0;
|
|
});
|
|
if (it != serviceMapBack.end()) {
|
|
info.emplace_back("uri [ " + it->first + " ]");
|
|
if (it->second != nullptr) {
|
|
it->second->DumpService(info, isClient);
|
|
}
|
|
} else {
|
|
info.emplace_back(args + ": Nothing to dump.");
|
|
}
|
|
} else {
|
|
info.emplace_back(" ExtensionRecords:");
|
|
for (auto &&service : serviceMapBack) {
|
|
info.emplace_back(" uri [" + service.first + "]");
|
|
if (service.second != nullptr) {
|
|
service.second->DumpService(info, isClient);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::DumpStateByUri(std::vector<std::string> &info, bool isClient, const std::string &args,
|
|
std::vector<std::string> ¶ms)
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "args:%{public}s, params size: %{public}zu", args.c_str(), params.size());
|
|
std::shared_ptr<AbilityRecord> extensionAbilityRecord = nullptr;
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto it = std::find_if(serviceMap_.begin(), serviceMap_.end(), [&args](const auto &service) {
|
|
return service.first.compare(args) == 0;
|
|
});
|
|
if (it != serviceMap_.end()) {
|
|
info.emplace_back("uri [ " + it->first + " ]");
|
|
extensionAbilityRecord = it->second;
|
|
} else {
|
|
info.emplace_back(args + ": Nothing to dump.");
|
|
}
|
|
}
|
|
if (extensionAbilityRecord != nullptr) {
|
|
extensionAbilityRecord->DumpService(info, params, isClient);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::GetExtensionRunningInfos(int upperLimit, std::vector<ExtensionRunningInfo> &info,
|
|
const int32_t userId, bool isPerm)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
auto serviceMapBack = GetServiceMap();
|
|
auto queryInfo = [&](ServiceMapType::reference service) {
|
|
if (static_cast<int>(info.size()) >= upperLimit) {
|
|
return;
|
|
}
|
|
auto abilityRecord = service.second;
|
|
CHECK_POINTER(abilityRecord);
|
|
|
|
if (isPerm) {
|
|
GetExtensionRunningInfo(abilityRecord, userId, info);
|
|
} else {
|
|
auto callingTokenId = IPCSkeleton::GetCallingTokenID();
|
|
auto tokenID = abilityRecord->GetApplicationInfo().accessTokenId;
|
|
if (callingTokenId == tokenID) {
|
|
GetExtensionRunningInfo(abilityRecord, userId, info);
|
|
}
|
|
}
|
|
};
|
|
std::for_each(serviceMapBack.begin(), serviceMapBack.end(), queryInfo);
|
|
}
|
|
|
|
void AbilityConnectManager::GetAbilityRunningInfos(std::vector<AbilityRunningInfo> &info, bool isPerm)
|
|
{
|
|
auto serviceMapBack = GetServiceMap();
|
|
auto queryInfo = [&info, isPerm](ServiceMapType::reference service) {
|
|
auto abilityRecord = service.second;
|
|
CHECK_POINTER(abilityRecord);
|
|
|
|
if (isPerm) {
|
|
DelayedSingleton<AbilityManagerService>::GetInstance()->GetAbilityRunningInfo(info, abilityRecord);
|
|
} else {
|
|
auto callingTokenId = IPCSkeleton::GetCallingTokenID();
|
|
auto tokenID = abilityRecord->GetApplicationInfo().accessTokenId;
|
|
if (callingTokenId == tokenID) {
|
|
DelayedSingleton<AbilityManagerService>::GetInstance()->GetAbilityRunningInfo(info, abilityRecord);
|
|
}
|
|
}
|
|
};
|
|
|
|
std::for_each(serviceMapBack.begin(), serviceMapBack.end(), queryInfo);
|
|
}
|
|
|
|
void AbilityConnectManager::GetExtensionRunningInfo(std::shared_ptr<AbilityRecord> &abilityRecord,
|
|
const int32_t userId, std::vector<ExtensionRunningInfo> &info)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
ExtensionRunningInfo extensionInfo;
|
|
AppExecFwk::RunningProcessInfo processInfo;
|
|
extensionInfo.extension = abilityRecord->GetElementName();
|
|
extensionInfo.type = abilityRecord->GetAbilityInfo().extensionAbilityType;
|
|
DelayedSingleton<AppScheduler>::GetInstance()->
|
|
GetRunningProcessInfoByToken(abilityRecord->GetToken(), processInfo);
|
|
extensionInfo.pid = processInfo.pid_;
|
|
extensionInfo.uid = processInfo.uid_;
|
|
extensionInfo.processName = processInfo.processName_;
|
|
extensionInfo.startTime = abilityRecord->GetStartTime();
|
|
ConnectListType connectRecordList = abilityRecord->GetConnectRecordList();
|
|
for (auto &connectRecord : connectRecordList) {
|
|
if (connectRecord == nullptr) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "connectRecord is nullptr.");
|
|
continue;
|
|
}
|
|
auto callerAbilityRecord = Token::GetAbilityRecordByToken(connectRecord->GetToken());
|
|
if (callerAbilityRecord == nullptr) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "callerAbilityRecord is nullptr.");
|
|
continue;
|
|
}
|
|
std::string package = callerAbilityRecord->GetAbilityInfo().bundleName;
|
|
extensionInfo.clientPackage.emplace_back(package);
|
|
}
|
|
info.emplace_back(extensionInfo);
|
|
}
|
|
|
|
void AbilityConnectManager::PauseExtensions()
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "begin.");
|
|
std::vector<sptr<IRemoteObject>> needTerminatedTokens;
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (auto it = serviceMap_.begin(); it != serviceMap_.end();) {
|
|
auto targetExtension = it->second;
|
|
if (targetExtension != nullptr && targetExtension->GetAbilityInfo().type == AbilityType::EXTENSION &&
|
|
(IsLauncher(targetExtension) || targetExtension->IsSceneBoard())) {
|
|
terminatingExtensionMap_.emplace(it->first, it->second);
|
|
it = serviceMap_.erase(it);
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "terminate ability:%{public}s.",
|
|
targetExtension->GetAbilityInfo().name.c_str());
|
|
needTerminatedTokens.push_back(targetExtension->GetToken());
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const auto &token : needTerminatedTokens) {
|
|
std::lock_guard lock(serialMutex_);
|
|
TerminateAbilityLocked(token);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveLauncherDeathRecipient()
|
|
{
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Call.");
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (auto it = serviceMap_.begin(); it != serviceMap_.end(); ++it) {
|
|
auto targetExtension = it->second;
|
|
if (targetExtension != nullptr && targetExtension->GetAbilityInfo().type == AbilityType::EXTENSION &&
|
|
(IsLauncher(targetExtension) || targetExtension->IsSceneBoard())) {
|
|
targetExtension->RemoveAbilityDeathRecipient();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AbilityConnectManager::IsLauncher(std::shared_ptr<AbilityRecord> serviceExtension) const
|
|
{
|
|
if (serviceExtension == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "param is nullptr");
|
|
return false;
|
|
}
|
|
return serviceExtension->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME &&
|
|
serviceExtension->GetAbilityInfo().bundleName == AbilityConfig::LAUNCHER_BUNDLE_NAME;
|
|
}
|
|
|
|
bool AbilityConnectManager::IsSampleManagement(std::shared_ptr<AbilityRecord> serviceExtension) const
|
|
{
|
|
if (serviceExtension == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "param is nullptr");
|
|
return false;
|
|
}
|
|
return serviceExtension->GetAbilityInfo().name == ABILITY_NAME_SAMPLE_MANAGEMENT &&
|
|
serviceExtension->GetAbilityInfo().bundleName == BUNDLE_NAME_SAMPLE_MANAGEMENT;
|
|
}
|
|
|
|
void AbilityConnectManager::KillProcessesByUserId() const
|
|
{
|
|
auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
|
|
if (appScheduler == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "appScheduler is nullptr");
|
|
return;
|
|
}
|
|
IN_PROCESS_CALL_WITHOUT_RET(appScheduler->KillProcessesByUserId(userId_));
|
|
}
|
|
|
|
void AbilityConnectManager::MoveToForeground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "ability record is null.");
|
|
return;
|
|
}
|
|
|
|
auto self(weak_from_this());
|
|
auto task = [abilityRecord, self]() {
|
|
auto selfObj = self.lock();
|
|
if (selfObj == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "mgr is invalid.");
|
|
return;
|
|
}
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "move to foreground timeout.");
|
|
selfObj->PrintTimeOutLog(abilityRecord, AbilityManagerService::FOREGROUND_TIMEOUT_MSG);
|
|
selfObj->HandleForegroundTimeoutTask(abilityRecord);
|
|
};
|
|
auto sessionInfo = abilityRecord->GetUIExtRequestSessionInfo();
|
|
if (sessionInfo != nullptr) {
|
|
abilityRecord->ForegroundAbility(task, sessionInfo);
|
|
abilityRecord->SetUIExtRequestSessionInfo(nullptr);
|
|
} else {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "SessionInfo is nullptr. Move to background");
|
|
abilityRecord->SetAbilityState(AbilityState::BACKGROUND);
|
|
DelayedSingleton<AppScheduler>::GetInstance()->MoveToBackground(abilityRecord->GetToken());
|
|
}
|
|
if (taskHandler_) {
|
|
taskHandler_->CancelTask(std::string("ConsumeSessionTimeout_") + std::to_string(abilityRecord->GetRecordId()));
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::MoveToBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Move the ui extension ability to background fail, ability record is null.");
|
|
return;
|
|
}
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Move the ui extension ability to background, ability:%{public}s.",
|
|
abilityRecord->GetAbilityInfo().name.c_str());
|
|
abilityRecord->SetIsNewWant(false);
|
|
|
|
auto self(weak_from_this());
|
|
auto task = [abilityRecord, self]() {
|
|
auto selfObj = self.lock();
|
|
if (selfObj == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "mgr is invalid.");
|
|
return;
|
|
}
|
|
CHECK_POINTER(abilityRecord);
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType) &&
|
|
selfObj->uiExtensionAbilityRecordMgr_ != nullptr && selfObj->IsCallerValid(abilityRecord)) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Start background timeout.");
|
|
selfObj->uiExtensionAbilityRecordMgr_->BackgroundTimeout(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "move to background timeout.");
|
|
selfObj->PrintTimeOutLog(abilityRecord, AbilityManagerService::BACKGROUND_TIMEOUT_MSG);
|
|
selfObj->CompleteBackground(abilityRecord);
|
|
};
|
|
abilityRecord->BackgroundAbility(task);
|
|
}
|
|
|
|
void AbilityConnectManager::CompleteForeground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr");
|
|
return;
|
|
}
|
|
if (abilityRecord->GetAbilityState() != AbilityState::FOREGROUNDING) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability state is %{public}d, it can't complete foreground.",
|
|
abilityRecord->GetAbilityState());
|
|
return;
|
|
}
|
|
|
|
abilityRecord->SetAbilityState(AbilityState::FOREGROUND);
|
|
if (abilityRecord->BackgroundAbilityWindowDelayed()) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Response background request.");
|
|
abilityRecord->DoBackgroundAbilityWindowDelayed(false);
|
|
DoBackgroundAbilityWindow(abilityRecord, abilityRecord->GetSessionInfo());
|
|
}
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
}
|
|
|
|
void AbilityConnectManager::HandleForegroundTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
std::lock_guard guard(serialMutex_);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr");
|
|
return;
|
|
}
|
|
if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType) &&
|
|
uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Start foreground timeout.");
|
|
uiExtensionAbilityRecordMgr_->ForegroundTimeout(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
abilityRecord->SetAbilityState(AbilityState::BACKGROUND);
|
|
abilityRecord->DoBackgroundAbilityWindowDelayed(false);
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
}
|
|
|
|
void AbilityConnectManager::CompleteBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
std::lock_guard lock(serialMutex_);
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr");
|
|
return;
|
|
}
|
|
if (abilityRecord->GetAbilityState() != AbilityState::BACKGROUNDING) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability state is %{public}d, it can't complete background.",
|
|
abilityRecord->GetAbilityState());
|
|
return;
|
|
}
|
|
abilityRecord->SetAbilityState(AbilityState::BACKGROUND);
|
|
// send application state to AppMS.
|
|
// notify AppMS to update application state.
|
|
DelayedSingleton<AppScheduler>::GetInstance()->MoveToBackground(abilityRecord->GetToken());
|
|
CompleteStartServiceReq(abilityRecord->GetURI());
|
|
// Abilities ahead of the one started were put in terminate list, we need to terminate them.
|
|
TerminateAbilityLocked(abilityRecord->GetToken());
|
|
}
|
|
|
|
void AbilityConnectManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId)
|
|
{
|
|
if (ability == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "ability is nullptr");
|
|
return;
|
|
}
|
|
|
|
AppExecFwk::RunningProcessInfo processInfo = {};
|
|
DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByToken(ability->GetToken(), processInfo);
|
|
if (processInfo.pid_ == 0) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "error: the ability[%{public}s], app may fork fail or not running.",
|
|
ability->GetAbilityInfo().name.data());
|
|
return;
|
|
}
|
|
int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT;
|
|
std::string msgContent = "ability:" + ability->GetAbilityInfo().name + " ";
|
|
switch (msgId) {
|
|
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
|
msgContent += "load timeout";
|
|
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
|
break;
|
|
case AbilityManagerService::ACTIVE_TIMEOUT_MSG:
|
|
msgContent += "active timeout";
|
|
break;
|
|
case AbilityManagerService::INACTIVE_TIMEOUT_MSG:
|
|
msgContent += "inactive timeout";
|
|
break;
|
|
case AbilityManagerService::FOREGROUND_TIMEOUT_MSG:
|
|
msgContent += "foreground timeout";
|
|
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
|
break;
|
|
case AbilityManagerService::BACKGROUND_TIMEOUT_MSG:
|
|
msgContent += "background timeout";
|
|
break;
|
|
case AbilityManagerService::TERMINATE_TIMEOUT_MSG:
|
|
msgContent += "terminate timeout";
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR,
|
|
"LIFECYCLE_TIMEOUT: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
|
"msg: %{public}s",
|
|
processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
|
ability->GetAbilityInfo().name.c_str(), msgContent.c_str());
|
|
AppExecFwk::AppfreezeManager::ParamInfo info = {
|
|
.typeId = typeId,
|
|
.pid = processInfo.pid_,
|
|
.eventName = AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT,
|
|
.bundleName = ability->GetAbilityInfo().bundleName,
|
|
.msg = msgContent
|
|
};
|
|
AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(info);
|
|
}
|
|
|
|
void AbilityConnectManager::MoveToTerminatingMap(const std::shared_ptr<AbilityRecord>& abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
auto& abilityInfo = abilityRecord->GetAbilityInfo();
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
terminatingExtensionMap_.emplace(abilityRecord->GetURI(), abilityRecord);
|
|
if (FRS_BUNDLE_NAME == abilityInfo.bundleName) {
|
|
AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name,
|
|
abilityInfo.moduleName);
|
|
serviceMap_.erase(
|
|
element.GetURI() + std::to_string(abilityRecord->GetWant().GetIntParam(FRS_APP_INDEX, 0)));
|
|
} else {
|
|
serviceMap_.erase(abilityRecord->GetURI());
|
|
}
|
|
if (IsSpecialAbility(abilityRecord->GetAbilityInfo())) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Moving ability: %{public}s", abilityRecord->GetURI().c_str());
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::AddUIExtWindowDeathRecipient(const sptr<IRemoteObject> &session)
|
|
{
|
|
CHECK_POINTER(session);
|
|
std::lock_guard lock(uiExtRecipientMapMutex_);
|
|
auto it = uiExtRecipientMap_.find(session);
|
|
if (it != uiExtRecipientMap_.end()) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "This death recipient has been added.");
|
|
return;
|
|
} else {
|
|
std::weak_ptr<AbilityConnectManager> thisWeakPtr(shared_from_this());
|
|
sptr<IRemoteObject::DeathRecipient> deathRecipient =
|
|
new AbilityConnectCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
|
|
auto abilityConnectManager = thisWeakPtr.lock();
|
|
if (abilityConnectManager) {
|
|
abilityConnectManager->OnUIExtWindowDied(remote);
|
|
}
|
|
});
|
|
if (!session->AddDeathRecipient(deathRecipient)) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "AddDeathRecipient failed.");
|
|
}
|
|
uiExtRecipientMap_.emplace(session, deathRecipient);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveUIExtWindowDeathRecipient(const sptr<IRemoteObject> &session)
|
|
{
|
|
CHECK_POINTER(session);
|
|
std::lock_guard lock(uiExtRecipientMapMutex_);
|
|
auto it = uiExtRecipientMap_.find(session);
|
|
if (it != uiExtRecipientMap_.end() && it->first != nullptr) {
|
|
it->first->RemoveDeathRecipient(it->second);
|
|
uiExtRecipientMap_.erase(it);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::OnUIExtWindowDied(const wptr<IRemoteObject> &remote)
|
|
{
|
|
auto object = remote.promote();
|
|
CHECK_POINTER(object);
|
|
if (taskHandler_) {
|
|
auto task = [object, connectManager = shared_from_this()]() {
|
|
connectManager->HandleUIExtWindowDiedTask(object);
|
|
};
|
|
taskHandler_->SubmitTask(task);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::HandleUIExtWindowDiedTask(const sptr<IRemoteObject> &remote)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call.");
|
|
CHECK_POINTER(remote);
|
|
std::shared_ptr<AbilityRecord> abilityRecord;
|
|
sptr<SessionInfo> sessionInfo;
|
|
{
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
auto it = uiExtensionMap_.find(remote);
|
|
if (it != uiExtensionMap_.end()) {
|
|
abilityRecord = it->second.first.lock();
|
|
sessionInfo = it->second.second;
|
|
uiExtensionMap_.erase(it);
|
|
} else {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "Died object can't find from map.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (abilityRecord) {
|
|
TerminateAbilityWindowLocked(abilityRecord, sessionInfo);
|
|
} else {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr");
|
|
}
|
|
RemoveUIExtWindowDeathRecipient(remote);
|
|
}
|
|
|
|
bool AbilityConnectManager::IsUIExtensionFocused(uint32_t uiExtensionTokenId, const sptr<IRemoteObject>& focusToken)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "called, id: %{public}u", uiExtensionTokenId);
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, false);
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
for (auto& item: uiExtensionMap_) {
|
|
auto uiExtension = item.second.first.lock();
|
|
auto sessionInfo = item.second.second;
|
|
if (uiExtension && uiExtension->GetApplicationInfo().accessTokenId == uiExtensionTokenId) {
|
|
if (uiExtensionAbilityRecordMgr_->IsFocused(uiExtension->GetUIExtensionAbilityId(), focusToken)) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "id: %{public}u, isFocused.", uiExtensionTokenId);
|
|
return true;
|
|
}
|
|
if (sessionInfo && sessionInfo->callerToken == focusToken) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
sptr<IRemoteObject> AbilityConnectManager::GetUIExtensionSourceToken(const sptr<IRemoteObject> &token)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Called");
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
for (auto &item : uiExtensionMap_) {
|
|
auto sessionInfo = item.second.second;
|
|
auto uiExtension = item.second.first.lock();
|
|
if (sessionInfo != nullptr && uiExtension->GetToken() != nullptr &&
|
|
uiExtension->GetToken()->AsObject() == token) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "The source token found.");
|
|
return sessionInfo->callerToken;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool AbilityConnectManager::IsWindowExtensionFocused(uint32_t extensionTokenId, const sptr<IRemoteObject>& focusToken)
|
|
{
|
|
std::lock_guard guard(windowExtensionMapMutex_);
|
|
for (auto& item: windowExtensionMap_) {
|
|
uint32_t windowExtTokenId = item.second.first;
|
|
auto sessionInfo = item.second.second;
|
|
if (windowExtTokenId == extensionTokenId && sessionInfo && sessionInfo->callerToken == focusToken) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void AbilityConnectManager::HandleProcessFrozen(const std::vector<int32_t> &pidList, int32_t uid)
|
|
{
|
|
auto taskHandler = taskHandler_;
|
|
if (!taskHandler) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "taskHandler null");
|
|
return;
|
|
}
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleProcessFrozen: %{public}d", uid);
|
|
std::unordered_set<int32_t> pidSet(pidList.begin(), pidList.end());
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
auto weakThis = weak_from_this();
|
|
for (auto [key, abilityRecord] : serviceMap_) {
|
|
if (abilityRecord && abilityRecord->GetUid() == uid &&
|
|
abilityRecord->GetAbilityInfo().extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE &&
|
|
pidSet.count(abilityRecord->GetPid()) > 0 &&
|
|
FROZEN_WHITE_LIST.count(abilityRecord->GetAbilityInfo().bundleName) == 0 &&
|
|
abilityRecord->IsConnectListEmpty() &&
|
|
!abilityRecord->GetKeepAlive() &&
|
|
abilityRecord->GetStartId() != 0) { // To be honest, this is expected to be true
|
|
taskHandler->SubmitTask([weakThis, record = abilityRecord]() {
|
|
auto connectManager = weakThis.lock();
|
|
if (record && connectManager) {
|
|
TAG_LOGI(AAFwkTag::ABILITYMGR, "TerminateRecord: %{public}s",
|
|
record->GetAbilityInfo().bundleName.c_str());
|
|
connectManager->TerminateRecord(record);
|
|
} else {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "connectManager null");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::PostExtensionDelayDisconnectTask(const std::shared_ptr<ConnectionRecord> &connectRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
CHECK_POINTER(taskHandler_);
|
|
CHECK_POINTER(connectRecord);
|
|
int32_t recordId = connectRecord->GetRecordId();
|
|
std::string taskName = std::string("DelayDisconnectTask_") + std::to_string(recordId);
|
|
|
|
auto abilityRecord = connectRecord->GetAbilityRecord();
|
|
CHECK_POINTER(abilityRecord);
|
|
auto typeName = abilityRecord->GetAbilityInfo().extensionTypeName;
|
|
int32_t delayTime = DelayedSingleton<ExtensionConfig>::GetInstance()->GetExtensionAutoDisconnectTime(typeName);
|
|
if (delayTime == AUTO_DISCONNECT_INFINITY) {
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "This extension needn't auto disconnect.");
|
|
return;
|
|
}
|
|
|
|
auto task = [connectRecord, self = weak_from_this()]() {
|
|
auto selfObj = self.lock();
|
|
if (selfObj == nullptr) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "mgr is invalid.");
|
|
return;
|
|
}
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Auto disconnect the Extension's connection.");
|
|
selfObj->HandleExtensionDisconnectTask(connectRecord);
|
|
};
|
|
taskHandler_->SubmitTask(task, taskName, delayTime);
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveExtensionDelayDisconnectTask(const std::shared_ptr<ConnectionRecord> &connectRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
CHECK_POINTER(taskHandler_);
|
|
CHECK_POINTER(connectRecord);
|
|
int32_t recordId = connectRecord->GetRecordId();
|
|
std::string taskName = std::string("DelayDisconnectTask_") + std::to_string(recordId);
|
|
taskHandler_->CancelTask(taskName);
|
|
}
|
|
|
|
void AbilityConnectManager::HandleExtensionDisconnectTask(const std::shared_ptr<ConnectionRecord> &connectRecord)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
|
|
std::lock_guard guard(serialMutex_);
|
|
CHECK_POINTER(connectRecord);
|
|
int result = connectRecord->DisconnectAbility();
|
|
if (result != ERR_OK) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Auto disconnect extension error, ret: %{public}d.", result);
|
|
}
|
|
if (connectRecord->GetConnectState() == ConnectionState::DISCONNECTED) {
|
|
connectRecord->CompleteDisconnect(ERR_OK, false);
|
|
RemoveConnectionRecordFromMap(connectRecord);
|
|
}
|
|
}
|
|
|
|
bool AbilityConnectManager::IsUIExtensionAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, false);
|
|
return UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType);
|
|
}
|
|
|
|
bool AbilityConnectManager::CheckUIExtensionAbilitySessionExist(
|
|
const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(abilityRecord, false);
|
|
std::lock_guard guard(uiExtensionMapMutex_);
|
|
for (auto it = uiExtensionMap_.begin(); it != uiExtensionMap_.end(); ++it) {
|
|
std::shared_ptr<AbilityRecord> uiExtAbility = it->second.first.lock();
|
|
if (abilityRecord == uiExtAbility) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void AbilityConnectManager::RemoveUIExtensionAbilityRecord(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(uiExtensionAbilityRecordMgr_);
|
|
uiExtensionAbilityRecordMgr_->RemoveExtensionRecord(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
|
|
void AbilityConnectManager::AddUIExtensionAbilityRecordToTerminatedList(
|
|
const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER(abilityRecord);
|
|
CHECK_POINTER(uiExtensionAbilityRecordMgr_);
|
|
uiExtensionAbilityRecordMgr_->AddExtensionRecordToTerminatedList(abilityRecord->GetUIExtensionAbilityId());
|
|
}
|
|
|
|
bool AbilityConnectManager::IsCallerValid(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
CHECK_POINTER_AND_RETURN_LOG(abilityRecord, false, "Invalid caller for UIExtension");
|
|
auto sessionInfo = abilityRecord->GetSessionInfo();
|
|
CHECK_POINTER_AND_RETURN_LOG(sessionInfo, false, "Invalid caller for UIExtension");
|
|
CHECK_POINTER_AND_RETURN_LOG(sessionInfo->sessionToken, false, "Invalid caller for UIExtension");
|
|
std::lock_guard lock(uiExtRecipientMapMutex_);
|
|
if (uiExtRecipientMap_.find(sessionInfo->sessionToken) == uiExtRecipientMap_.end()) {
|
|
TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid caller for UIExtension.");
|
|
return false;
|
|
}
|
|
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "The caller survival.");
|
|
return true;
|
|
}
|
|
|
|
std::shared_ptr<AAFwk::AbilityRecord> AbilityConnectManager::GetUIExtensionRootHostInfo(const sptr<IRemoteObject> token)
|
|
{
|
|
CHECK_POINTER_AND_RETURN(token, nullptr);
|
|
CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, nullptr);
|
|
return uiExtensionAbilityRecordMgr_->GetUIExtensionRootHostInfo(token);
|
|
}
|
|
|
|
void AbilityConnectManager::SignRestartAppFlag(const std::string &bundleName)
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (auto &[key, abilityRecord] : serviceMap_) {
|
|
if (abilityRecord == nullptr || abilityRecord->GetApplicationInfo().bundleName != bundleName) {
|
|
continue;
|
|
}
|
|
abilityRecord->SetRestartAppFlag(true);
|
|
}
|
|
}
|
|
|
|
void AbilityConnectManager::DeleteInvalidServiceRecord(const std::string &bundleName)
|
|
{
|
|
TAG_LOGD(AAFwkTag::ABILITYMGR, "Delete invalid record by %{public}s.", bundleName.c_str());
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
for (auto it = serviceMap_.begin(); it != serviceMap_.end();) {
|
|
if (it->second != nullptr && it->second->GetApplicationInfo().bundleName == bundleName &&
|
|
!IsUIExtensionAbility(it->second) && !IsAbilityNeedKeepAlive(it->second)) {
|
|
it = serviceMap_.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AbilityConnectManager::AddToServiceMap(const std::string &key, std::shared_ptr<AbilityRecord> abilityRecord)
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
if (abilityRecord == nullptr) {
|
|
return false;
|
|
}
|
|
auto insert = serviceMap_.emplace(key, abilityRecord);
|
|
return insert.second;
|
|
}
|
|
|
|
AbilityConnectManager::ServiceMapType AbilityConnectManager::GetServiceMap()
|
|
{
|
|
std::lock_guard lock(serviceMapMutex_);
|
|
return serviceMap_;
|
|
}
|
|
|
|
void AbilityConnectManager::AddConnectObjectToMap(sptr<IRemoteObject> connectObject,
|
|
const ConnectListType &connectRecordList, bool updateOnly)
|
|
{
|
|
if (!updateOnly) {
|
|
AddConnectDeathRecipient(connectObject);
|
|
}
|
|
std::lock_guard guard(connectMapMutex_);
|
|
connectMap_[connectObject] = connectRecordList;
|
|
}
|
|
|
|
EventInfo AbilityConnectManager::BuildEventInfo(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
EventInfo eventInfo;
|
|
if (abilityRecord == nullptr) {
|
|
TAG_LOGE(AAFwkTag::ABILITYMGR, "build eventInfo failed, abilityRecord is nullptr");
|
|
return eventInfo;
|
|
}
|
|
AppExecFwk::RunningProcessInfo processInfo;
|
|
DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByToken(abilityRecord->GetToken(), processInfo);
|
|
eventInfo.pid = processInfo.pid_;
|
|
eventInfo.processName = processInfo.processName_;
|
|
eventInfo.time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
|
auto callerPid = abilityRecord->GetWant().GetIntParam(Want::PARAM_RESV_CALLER_PID, -1);
|
|
eventInfo.callerPid = callerPid == -1 ? IPCSkeleton::GetCallingPid() : callerPid;
|
|
DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByPid(eventInfo.callerPid, processInfo);
|
|
eventInfo.callerPid = processInfo.pid_;
|
|
eventInfo.callerProcessName = processInfo.processName_;
|
|
if (!abilityRecord->IsCreateByConnect()) {
|
|
auto abilityInfo = abilityRecord->GetAbilityInfo();
|
|
eventInfo.extensionType = static_cast<int32_t>(abilityInfo.extensionAbilityType);
|
|
eventInfo.userId = userId_;
|
|
eventInfo.bundleName = abilityInfo.bundleName;
|
|
eventInfo.moduleName = abilityInfo.moduleName;
|
|
eventInfo.abilityName = abilityInfo.name;
|
|
}
|
|
return eventInfo;
|
|
}
|
|
|
|
void AbilityConnectManager::UpdateUIExtensionInfo(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
|
{
|
|
if (abilityRecord == nullptr ||
|
|
!UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) {
|
|
return;
|
|
}
|
|
|
|
WantParams wantParams;
|
|
auto uiExtensionAbilityId = abilityRecord->GetUIExtensionAbilityId();
|
|
wantParams.SetParam(UIEXTENSION_ABILITY_ID, AAFwk::Integer::Box(uiExtensionAbilityId));
|
|
auto rootHostRecord = GetUIExtensionRootHostInfo(abilityRecord->GetToken());
|
|
if (rootHostRecord != nullptr) {
|
|
auto rootHostPid = rootHostRecord->GetPid();
|
|
wantParams.SetParam(UIEXTENSION_ROOT_HOST_PID, AAFwk::Integer::Box(rootHostPid));
|
|
}
|
|
if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) {
|
|
// Applicable only to preloadUIExtension scenarios
|
|
auto rootHostPid = IPCSkeleton::GetCallingPid();
|
|
wantParams.SetParam(UIEXTENSION_ROOT_HOST_PID, AAFwk::Integer::Box(rootHostPid));
|
|
}
|
|
abilityRecord->UpdateUIExtensionInfo(wantParams);
|
|
}
|
|
|
|
std::string AbilityConnectManager::GenerateBundleName(const AbilityRequest &abilityRequest) const
|
|
{
|
|
auto bundleName = abilityRequest.abilityInfo.bundleName;
|
|
if (AbilityRuntime::StartupUtil::IsSupportAppClone(abilityRequest.abilityInfo.extensionAbilityType)) {
|
|
auto appCloneIndex = abilityRequest.want.GetIntParam(Want::PARAM_APP_CLONE_INDEX_KEY, 0);
|
|
if (appCloneIndex > 0) {
|
|
bundleName = std::to_string(appCloneIndex) + bundleName;
|
|
}
|
|
}
|
|
return bundleName;
|
|
}
|
|
} // namespace AAFwk
|
|
} // namespace OHOS
|