Files
ability_ability_runtime/services/abilitymgr/src/ability_connect_manager.cpp
T
donglin 9cfbfca648 excute disconnect before ability restart
Signed-off-by: donglin <donglin9@huawei.com>
Change-Id: I09b27df53654a1eb98426e6ab541859437f37727
2022-09-14 15:01:08 +08:00

1301 lines
54 KiB
C++

/*
* Copyright (c) 2021-2022 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 "ability_connect_callback_stub.h"
#include "ability_manager_errors.h"
#include "ability_manager_service.h"
#include "ability_util.h"
#include "hitrace_meter.h"
#include "hilog_wrapper.h"
#include "in_process_call_wrapper.h"
#include "parameter.h"
namespace OHOS {
namespace AAFwk {
AbilityConnectManager::AbilityConnectManager(int userId) : userId_(userId)
{}
AbilityConnectManager::~AbilityConnectManager()
{}
int AbilityConnectManager::StartAbility(const AbilityRequest &abilityRequest)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
return StartAbilityLocked(abilityRequest);
}
int AbilityConnectManager::TerminateAbility(const sptr<IRemoteObject> &token)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
return TerminateAbilityLocked(token);
}
int AbilityConnectManager::TerminateAbility(const std::shared_ptr<AbilityRecord> &caller, int requestCode)
{
HILOG_INFO("Terminate ability.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
std::shared_ptr<AbilityRecord> targetAbility = nullptr;
int result = static_cast<int>(ABILITY_VISIBLE_FALSE_DENY_REQUEST);
std::for_each(serviceMap_.begin(),
serviceMap_.end(),
[&targetAbility, &caller, requestCode, &result](ServiceMapType::reference service) {
auto callerList = service.second->GetCallerRecordList();
for (auto &it : callerList) {
if (it->GetCaller() == caller && it->GetRequestCode() == requestCode) {
targetAbility = service.second;
if (targetAbility) {
auto abilityMs = DelayedSingleton<AbilityManagerService>::GetInstance();
CHECK_POINTER(abilityMs);
result = abilityMs->JudgeAbilityVisibleControl(targetAbility->GetAbilityInfo());
}
break;
}
}
});
if (!targetAbility) {
HILOG_ERROR("targetAbility error.");
return NO_FOUND_ABILITY_BY_CALLER;
}
if (result != ERR_OK) {
HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__);
return result;
}
return TerminateAbilityLocked(targetAbility->GetToken());
}
int AbilityConnectManager::StopServiceAbility(const AbilityRequest &abilityRequest)
{
HILOG_INFO("Stop Service ability.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
return StopServiceAbilityLocked(abilityRequest);
}
int AbilityConnectManager::TerminateAbilityResult(const sptr<IRemoteObject> &token, int startId)
{
HILOG_INFO("Terminate ability result.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
return TerminateAbilityResultLocked(token, startId);
}
int AbilityConnectManager::StartAbilityLocked(const AbilityRequest &abilityRequest)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Start ability locked, ability_name: %{public}s",
abilityRequest.want.GetElement().GetURI().c_str());
std::shared_ptr<AbilityRecord> targetService;
bool isLoadedAbility = false;
GetOrCreateServiceRecord(abilityRequest, false, targetService, isLoadedAbility);
CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE);
targetService->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode);
if (!isLoadedAbility) {
LoadAbility(targetService);
} else if (targetService->IsAbilityState(AbilityState::ACTIVE)) {
// It may have been started through connect
CommandAbility(targetService);
} else {
HILOG_ERROR("Target service is already activating.");
return START_SERVICE_ABILITY_ACTIVATING;
}
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;
}
int AbilityConnectManager::TerminateAbilityLocked(const sptr<IRemoteObject> &token)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Terminate ability locked.");
auto abilityRecord = GetServiceRecordByToken(token);
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
if (abilityRecord->IsTerminating()) {
HILOG_INFO("Ability is on terminating.");
return ERR_OK;
}
if (!abilityRecord->GetConnectRecordList().empty()) {
HILOG_INFO("Target service has been connected. Post disconnect task.");
auto connectRecordList = abilityRecord->GetConnectRecordList();
HandleTerminateDisconnectTask(connectRecordList);
}
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
HILOG_WARN("Disconnect ability terminate timeout.");
connectManager->HandleStopTimeoutTask(abilityRecord);
};
abilityRecord->Terminate(timeoutTask);
return ERR_OK;
}
int AbilityConnectManager::TerminateAbilityResultLocked(const sptr<IRemoteObject> &token, int startId)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Terminate ability result locked, startId: %{public}d", startId);
CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE);
auto abilityRecord = Token::GetAbilityRecordByToken(token);
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
if (abilityRecord->GetStartId() != startId) {
HILOG_ERROR("Start id not equal.");
return TERMINATE_ABILITY_RESULT_FAILED;
}
return TerminateAbilityLocked(token);
}
int AbilityConnectManager::StopServiceAbilityLocked(const AbilityRequest &abilityRequest)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Stop service ability locked.");
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName,
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
auto abilityRecord = GetServiceRecordByElementName(element.GetURI());
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
if (abilityRecord->IsTerminating()) {
HILOG_INFO("Ability is on terminating.");
return ERR_OK;
}
if (!abilityRecord->GetConnectRecordList().empty()) {
HILOG_INFO("Target service has been connected. Post disconnect task.");
auto connectRecordList = abilityRecord->GetConnectRecordList();
HandleTerminateDisconnectTask(connectRecordList);
}
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
HILOG_WARN("Disconnect ability terminate timeout.");
connectManager->HandleStopTimeoutTask(abilityRecord);
};
abilityRecord->Terminate(timeoutTask);
return ERR_OK;
}
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__);
AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName,
abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName);
auto serviceMapIter = serviceMap_.find(element.GetURI());
if (serviceMapIter == serviceMap_.end()) {
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->SetRestarting(abilityRequest.restart, abilityRequest.restartCount);
}
serviceMap_.emplace(element.GetURI(), targetService);
isLoadedAbility = false;
} else {
targetService = serviceMapIter->second;
if (targetService != nullptr) {
// want may be changed for the same ability.
targetService->SetWant(abilityRequest.want);
}
isLoadedAbility = true;
}
}
void AbilityConnectManager::GetConnectRecordListFromMap(
const sptr<IAbilityConnection> &connect, std::list<std::shared_ptr<ConnectionRecord>> &connectRecordList)
{
auto connectMapIter = connectMap_.find(connect->AsObject());
if (connectMapIter != connectMap_.end()) {
connectRecordList = connectMapIter->second;
}
}
int AbilityConnectManager::ConnectAbilityLocked(const AbilityRequest &abilityRequest,
const sptr<IAbilityConnection> &connect, const sptr<IRemoteObject> &callerToken)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Connect ability called, callee:%{public}s.", abilityRequest.want.GetElement().GetURI().c_str());
std::lock_guard<std::recursive_mutex> guard(Lock_);
// 1. get target service ability record, and check whether it has been loaded.
std::shared_ptr<AbilityRecord> targetService;
bool isLoadedAbility = false;
GetOrCreateServiceRecord(abilityRequest, true, targetService, isLoadedAbility);
CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE);
// 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)) {
HILOG_INFO("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);
connectRecordList.push_back(connectRecord);
if (isCallbackConnected) {
RemoveConnectDeathRecipient(connect);
connectMap_.erase(connectMap_.find(connect->AsObject()));
}
AddConnectDeathRecipient(connect);
connectMap_.emplace(connect->AsObject(), connectRecordList);
// 5. load or connect ability
int ret = ERR_OK;
if (!isLoadedAbility) {
LoadAbility(targetService);
} else if (targetService->IsAbilityState(AbilityState::ACTIVE)) {
// this service ability has not first connect
if (targetService->GetConnectRecordList().size() > 1) {
if (eventHandler_ != nullptr) {
auto task = [connectRecord]() { connectRecord->CompleteConnect(ERR_OK); };
eventHandler_->PostTask(task);
}
} else {
ConnectAbility(targetService);
}
} else {
HILOG_ERROR("Target service ability is activating, connect failed");
targetService->RemoveConnectRecordFromList(connectRecord);
RemoveConnectionRecordFromMap(connectRecord);
ret = START_SERVICE_ABILITY_ACTIVATING;
}
auto token = targetService->GetToken();
auto preToken = iface_cast<Token>(connectRecord->GetToken());
DelayedSingleton<AppScheduler>::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1);
return ret;
}
int AbilityConnectManager::DisconnectAbilityLocked(const sptr<IAbilityConnection> &connect)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
HILOG_INFO("Disconnect ability begin.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
// 1. check whether callback was connected.
ConnectListType connectRecordList;
GetConnectRecordListFromMap(connect, connectRecordList);
if (connectRecordList.empty()) {
HILOG_ERROR("Can't find the connect list from connect map by callback.");
return CONNECTION_NOT_EXIST;
}
// 2. schedule disconnect to target service
for (auto &connectRecord : connectRecordList) {
if (connectRecord) {
auto abilityRecord = connectRecord->GetAbilityRecord();
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
HILOG_INFO("Disconnect ability, caller:%{public}s.", abilityRecord->GetAbilityInfo().name.c_str());
auto abilityMs = DelayedSingleton<AbilityManagerService>::GetInstance();
CHECK_POINTER_AND_RETURN(abilityMs, GET_ABILITY_SERVICE_FAILED);
int result = abilityMs->JudgeAbilityVisibleControl(abilityRecord->GetAbilityInfo());
if (result != ERR_OK) {
HILOG_ERROR("Judge ability visible error.");
return result;
}
int ret = connectRecord->DisconnectAbility();
if (ret != ERR_OK) {
HILOG_ERROR("Disconnect ability fail , ret = %{public}d.", ret);
return ret;
}
}
}
// 3. target service has another connection, this record callback disconnected directly.
if (eventHandler_ != nullptr) {
auto task = [connectRecordList, connectManager = shared_from_this()]() {
connectManager->HandleDisconnectTask(connectRecordList);
};
eventHandler_->PostTask(task);
}
return ERR_OK;
}
int AbilityConnectManager::AttachAbilityThreadLocked(
const sptr<IAbilityScheduler> &scheduler, const sptr<IRemoteObject> &token)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto abilityRecord = GetServiceRecordByToken(token);
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
if (eventHandler_ != nullptr) {
int recordId = abilityRecord->GetRecordId();
std::string taskName = std::string("LoadTimeout_") + std::to_string(recordId);
eventHandler_->RemoveTask(taskName);
eventHandler_->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId());
}
std::string element = abilityRecord->GetWant().GetElement().GetURI();
HILOG_INFO("Ability: %{public}s", element.c_str());
abilityRecord->SetScheduler(scheduler);
abilityRecord->Inactivate();
return ERR_OK;
}
void AbilityConnectManager::OnAbilityRequestDone(const sptr<IRemoteObject> &token, const int32_t state)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto abilityState = DelayedSingleton<AppScheduler>::GetInstance()->ConvertToAppAbilityState(state);
auto abilityRecord = GetServiceRecordByToken(token);
CHECK_POINTER(abilityRecord);
std::string element = abilityRecord->GetWant().GetElement().GetURI();
HILOG_INFO("Ability: %{public}s", element.c_str());
if (abilityState == AppAbilityState::ABILITY_STATE_FOREGROUND) {
abilityRecord->Inactivate();
} else if (abilityState == AppAbilityState::ABILITY_STATE_BACKGROUND) {
DelayedSingleton<AppScheduler>::GetInstance()->TerminateAbility(token, false);
RemoveServiceAbility(abilityRecord);
}
}
void AbilityConnectManager::OnAppStateChanged(const AppInfo &info)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
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<std::recursive_mutex> guard(Lock_);
auto abilityRecord = GetServiceRecordByToken(token);
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
std::string element = abilityRecord->GetWant().GetElement().GetURI();
int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast<AbilityLifeCycleState>(state));
std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast<AbilityState>(targetState));
HILOG_INFO("Ability: %{public}s, state: %{public}s", element.c_str(), abilityState.c_str());
switch (state) {
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);
}
return DispatchInactive(abilityRecord, state);
}
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: {
HILOG_WARN("Don't support transiting state: %{public}d", state);
return ERR_INVALID_VALUE;
}
}
}
int AbilityConnectManager::ScheduleConnectAbilityDoneLocked(
const sptr<IRemoteObject> &token, const sptr<IRemoteObject> &remoteObject)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
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->GetWant().GetElement().GetURI();
HILOG_DEBUG("Connect ability done, ability: %{public}s.", element.c_str());
if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) &&
(!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) {
HILOG_ERROR("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);
}
abilityRecord->SetConnRemoteObject(remoteObject);
// There may be multiple callers waiting for the connection result
auto connectRecordList = abilityRecord->GetConnectRecordList();
for (auto &connectRecord : connectRecordList) {
connectRecord->ScheduleConnectAbilityDone();
}
return ERR_OK;
}
int AbilityConnectManager::ScheduleDisconnectAbilityDoneLocked(const sptr<IRemoteObject> &token)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto abilityRecord = GetServiceRecordByToken(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)) {
HILOG_ERROR("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->GetWant().GetElement().GetURI();
HILOG_INFO("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) {
HILOG_INFO("Service ability has no any connection, and not started , need terminate.");
auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() {
HILOG_WARN("Disconnect ability terminate timeout.");
connectManager->HandleStopTimeoutTask(abilityRecord);
};
abilityRecord->Terminate(timeoutTask);
}
RemoveConnectionRecordFromMap(connect);
return ERR_OK;
}
int AbilityConnectManager::ScheduleCommandAbilityDoneLocked(const sptr<IRemoteObject> &token)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
std::lock_guard<std::recursive_mutex> guard(Lock_);
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->GetWant().GetElement().GetURI();
HILOG_DEBUG("Ability: %{public}s", element.c_str());
if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) &&
(!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) {
HILOG_ERROR("Ability record state is not inactive ,state: %{public}d", abilityRecord->GetAbilityState());
return INVALID_CONNECTION_STATE;
}
// complete command and pop waiting start ability from queue.
CompleteCommandAbility(abilityRecord);
return ERR_OK;
}
void AbilityConnectManager::CompleteCommandAbility(std::shared_ptr<AbilityRecord> abilityRecord)
{
CHECK_POINTER(abilityRecord);
if (eventHandler_) {
int recordId = abilityRecord->GetRecordId();
std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") +
std::to_string(abilityRecord->GetStartId());
eventHandler_->RemoveTask(taskName);
}
abilityRecord->SetAbilityState(AbilityState::ACTIVE);
}
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetServiceRecordByElementName(const std::string &element)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto mapIter = serviceMap_.find(element);
if (mapIter != serviceMap_.end()) {
return mapIter->second;
}
return nullptr;
}
std::shared_ptr<AbilityRecord> AbilityConnectManager::GetServiceRecordByToken(const sptr<IRemoteObject> &token)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto IsMatch = [token](auto service) {
if (!service.second) {
return false;
}
sptr<IRemoteObject> srcToken = service.second->GetToken();
return srcToken == token;
};
auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch);
if (serviceRecord != serviceMap_.end()) {
return serviceRecord->second;
}
return nullptr;
}
std::list<std::shared_ptr<ConnectionRecord>> AbilityConnectManager::GetConnectRecordListByCallback(
sptr<IAbilityConnection> callback)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
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::GetAbilityRecordByEventId(int64_t eventId)
{
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto IsMatch = [eventId](auto service) {
if (!service.second) {
return false;
}
return eventId == service.second->GetEventId();
};
auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch);
if (serviceRecord != serviceMap_.end()) {
return serviceRecord->second;
}
return nullptr;
}
void AbilityConnectManager::RemoveAll()
{
serviceMap_.clear();
connectMap_.clear();
}
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()) {
HILOG_ERROR("Root launcher restart is out of max count.");
RemoveServiceAbility(abilityRecord);
return;
}
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();
}
}
}
DelayedSingleton<AppScheduler>::GetInstance()->LoadAbility(
token, perToken, abilityRecord->GetAbilityInfo(), abilityRecord->GetApplicationInfo(),
abilityRecord->GetWant());
}
void AbilityConnectManager::PostTimeOutTask(const std::shared_ptr<AbilityRecord> &abilityRecord, uint32_t messageId)
{
CHECK_POINTER(abilityRecord);
CHECK_POINTER(eventHandler_);
if (messageId != AbilityConnectManager::LOAD_TIMEOUT_MSG &&
messageId != AbilityConnectManager::CONNECT_TIMEOUT_MSG) {
HILOG_ERROR("Timeout task messageId is error.");
return;
}
int recordId;
std::string taskName;
int resultCode;
uint32_t delayTime;
if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) {
// first load ability, There is at most one connect record.
recordId = abilityRecord->GetRecordId();
taskName = std::string("LoadTimeout_") + std::to_string(recordId);
resultCode = LOAD_ABILITY_TIMEOUT;
delayTime = AbilityManagerService::LOAD_TIMEOUT;
} else {
auto connectRecord = abilityRecord->GetConnectingRecord();
CHECK_POINTER(connectRecord);
recordId = connectRecord->GetRecordId();
taskName = std::string("ConnectTimeout_") + std::to_string(recordId);
resultCode = CONNECTION_TIMEOUT;
delayTime = AbilityManagerService::CONNECT_TIMEOUT;
}
// 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) {
HILOG_DEBUG("Hook_mode: no timeoutTask");
return;
}
auto timeoutTask = [abilityRecord, connectManager = shared_from_this(), resultCode]() {
HILOG_WARN("Connect or load ability timeout.");
connectManager->HandleStartTimeoutTask(abilityRecord, resultCode);
};
eventHandler_->PostTask(timeoutTask, taskName, delayTime);
}
void AbilityConnectManager::HandleStartTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord, int resultCode)
{
HILOG_DEBUG("Complete connect or load ability timeout.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(abilityRecord);
auto connectingList = abilityRecord->GetConnectingRecordList();
for (auto &connectRecord : connectingList) {
if (connectRecord == nullptr) {
HILOG_WARN("ConnectRecord is nullptr.");
continue;
}
connectRecord->CompleteDisconnect(ERR_OK, true);
abilityRecord->RemoveConnectRecordFromList(connectRecord);
RemoveConnectionRecordFromMap(connectRecord);
}
if (resultCode == LOAD_ABILITY_TIMEOUT) {
HILOG_DEBUG("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 (abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
// terminate the timeout root launcher.
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(abilityRecord->GetToken());
if (resultCode == LOAD_ABILITY_TIMEOUT) {
StartRootLauncher(abilityRecord);
}
}
}
void AbilityConnectManager::HandleCommandTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
HILOG_DEBUG("HandleCommandTimeoutTask start");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(abilityRecord);
if (abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
HILOG_DEBUG("Handle root launcher command timeout.");
// terminate the timeout root launcher.
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(abilityRecord->GetToken());
}
HILOG_DEBUG("HandleCommandTimeoutTask 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.restart = true;
requestInfo.restartCount = abilityRecord->GetRestartCount() - 1;
HILOG_DEBUG("restart root launcher, number:%{public}d", requestInfo.restartCount);
StartAbilityLocked(requestInfo);
}
void AbilityConnectManager::HandleStopTimeoutTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
HILOG_DEBUG("Complete stop ability timeout start.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(abilityRecord);
TerminateDone(abilityRecord);
}
void AbilityConnectManager::HandleDisconnectTask(const ConnectListType &connectlist)
{
HILOG_DEBUG("Complete disconnect ability.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
for (auto &connectRecord : connectlist) {
if (!connectRecord) {
continue;
}
auto targetService = connectRecord->GetAbilityRecord();
if (targetService && connectRecord->GetConnectState() == ConnectionState::DISCONNECTED &&
targetService->GetConnectRecordList().size() > 1) {
HILOG_WARN("This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId());
connectRecord->CompleteDisconnect(ERR_OK, false);
targetService->RemoveConnectRecordFromList(connectRecord);
RemoveConnectionRecordFromMap(connectRecord);
};
}
}
void AbilityConnectManager::HandleTerminateDisconnectTask(const ConnectListType& connectlist)
{
HILOG_DEBUG("Disconnect ability when terminate.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
for (auto& connectRecord : connectlist) {
if (!connectRecord) {
continue;
}
auto targetService = connectRecord->GetAbilityRecord();
if (targetService) {
HILOG_WARN("This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId());
connectRecord->CompleteDisconnect(ERR_OK, true);
targetService->RemoveConnectRecordFromList(connectRecord);
RemoveConnectionRecordFromMap(connectRecord);
};
}
}
int AbilityConnectManager::DispatchInactive(const std::shared_ptr<AbilityRecord> &abilityRecord, int state)
{
CHECK_POINTER_AND_RETURN(eventHandler_, ERR_INVALID_VALUE);
if (!abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) {
HILOG_ERROR("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->GetEventId());
// complete inactive
abilityRecord->SetAbilityState(AbilityState::INACTIVE);
if (abilityRecord->IsCreateByConnect()) {
ConnectAbility(abilityRecord);
} else {
CommandAbility(abilityRecord);
}
return ERR_OK;
}
int AbilityConnectManager::DispatchTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
// remove terminate timeout task
if (eventHandler_ != nullptr) {
eventHandler_->RemoveTask(std::to_string(abilityRecord->GetEventId()));
}
// 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 (eventHandler_ != 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()]() {
HILOG_ERROR("Command ability timeout. %{public}s", abilityRecord->GetAbilityInfo().name.c_str());
connectManager->HandleCommandTimeoutTask(abilityRecord);
};
eventHandler_->PostTask(timeoutTask, taskName, AbilityManagerService::COMMAND_TIMEOUT);
// scheduling command ability
abilityRecord->CommandAbility();
}
}
void AbilityConnectManager::TerminateDone(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) {
std::string expect = AbilityRecord::ConvertAbilityState(AbilityState::TERMINATING);
std::string actual = AbilityRecord::ConvertAbilityState(abilityRecord->GetAbilityState());
HILOG_ERROR(
"Transition life state error. expect %{public}s, actual %{public}s", expect.c_str(), actual.c_str());
return;
}
DelayedSingleton<AppScheduler>::GetInstance()->TerminateAbility(abilityRecord->GetToken(), false);
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(const std::shared_ptr<ConnectionRecord> &connection)
{
for (auto &connectCallback : connectMap_) {
auto &connectList = connectCallback.second;
auto connectRecord = std::find(connectList.begin(), connectList.end(), connection);
if (connectRecord != connectList.end()) {
HILOG_INFO("Remove connrecord(%{public}d) from maplist.", (*connectRecord)->GetRecordId());
connectList.remove(connection);
if (connectList.empty()) {
HILOG_INFO("Remove connlist from map.");
sptr<IAbilityConnection> connect = iface_cast<IAbilityConnection>(connectCallback.first);
RemoveConnectDeathRecipient(connect);
connectMap_.erase(connectCallback.first);
}
return;
}
}
}
void AbilityConnectManager::RemoveServiceAbility(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
CHECK_POINTER(abilityRecord);
const AppExecFwk::AbilityInfo &abilityInfo = abilityRecord->GetAbilityInfo();
AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName,
abilityInfo.name, abilityInfo.moduleName);
HILOG_INFO("Remove service(%{public}s) from map.", element.GetURI().c_str());
auto it = serviceMap_.find(element.GetURI());
if (it != serviceMap_.end()) {
HILOG_INFO("Remove service(%{public}s) from map.", abilityInfo.name.c_str());
serviceMap_.erase(it);
}
}
void AbilityConnectManager::AddConnectDeathRecipient(const sptr<IAbilityConnection> &connect)
{
CHECK_POINTER(connect);
CHECK_POINTER(connect->AsObject());
auto it = recipientMap_.find(connect->AsObject());
if (it != recipientMap_.end()) {
HILOG_ERROR("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->OnCallBackDied(remote);
}
});
connect->AsObject()->AddDeathRecipient(deathRecipient);
recipientMap_.emplace(connect->AsObject(), deathRecipient);
}
}
void AbilityConnectManager::RemoveConnectDeathRecipient(const sptr<IAbilityConnection> &connect)
{
CHECK_POINTER(connect);
CHECK_POINTER(connect->AsObject());
auto it = recipientMap_.find(connect->AsObject());
if (it != recipientMap_.end()) {
it->first->RemoveDeathRecipient(it->second);
recipientMap_.erase(it);
return;
}
}
void AbilityConnectManager::OnCallBackDied(const wptr<IRemoteObject> &remote)
{
auto object = remote.promote();
CHECK_POINTER(object);
if (eventHandler_) {
auto task = [object, connectManager = shared_from_this()]() { connectManager->HandleCallBackDiedTask(object); };
eventHandler_->PostTask(task, TASK_ON_CALLBACK_DIED);
}
}
void AbilityConnectManager::HandleCallBackDiedTask(const sptr<IRemoteObject> &connect)
{
HILOG_INFO("Handle call back died task.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(connect);
auto it = connectMap_.find(connect);
if (it != connectMap_.end()) {
ConnectListType connectRecordList = it->second;
for (auto &connRecord : connectRecordList) {
connRecord->ClearConnCallBack();
}
} else {
HILOG_INFO("Died object can't find from conn map.");
return;
}
sptr<IAbilityConnection> object = iface_cast<IAbilityConnection>(connect);
DisconnectAbilityLocked(object);
}
void AbilityConnectManager::OnAbilityDied(const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
{
HILOG_INFO("On ability died.");
CHECK_POINTER(abilityRecord);
if (abilityRecord->GetAbilityInfo().type != AbilityType::SERVICE &&
abilityRecord->GetAbilityInfo().type != AbilityType::EXTENSION) {
HILOG_DEBUG("Ability type is not service.");
return;
}
if (eventHandler_) {
auto task = [abilityRecord, connectManager = shared_from_this(), currentUserId]() {
connectManager->HandleAbilityDiedTask(abilityRecord, currentUserId);
};
eventHandler_->PostTask(task, TASK_ON_ABILITY_DIED);
}
}
void AbilityConnectManager::OnTimeOut(uint32_t msgId, int64_t eventId)
{
HILOG_DEBUG("On timeout, msgId is %{public}d", msgId);
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto abilityRecord = GetAbilityRecordByEventId(eventId);
if (abilityRecord == nullptr) {
HILOG_ERROR("AbilityConnectManager on time out event: ability record is nullptr.");
return;
}
HILOG_DEBUG("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)
{
HILOG_DEBUG("HandleInactiveTimeout start");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(ability);
if (ability->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
HILOG_DEBUG("Handle root launcher inactive timeout.");
// terminate the timeout root launcher.
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(ability->GetToken());
}
HILOG_DEBUG("HandleInactiveTimeout end");
}
bool AbilityConnectManager::IsAbilityNeedRestart(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
auto bms = AbilityUtil::GetBundleManager();
CHECK_POINTER_AND_RETURN(bms, false);
std::vector<AppExecFwk::BundleInfo> bundleInfos;
bool getBundleInfos = bms->GetBundleInfos(OHOS::AppExecFwk::GET_BUNDLE_DEFAULT, bundleInfos, USER_ID_NO_HEAD);
if (!getBundleInfos) {
HILOG_ERROR("Handle ability died task, get bundle infos failed");
return false;
}
auto CheckIsAbilityKeepAlive = [](const AppExecFwk::HapModuleInfo &hapModuleInfo,
const std::string processName, std::string &mainElement) {
if (!hapModuleInfo.isModuleJson) {
// old application model
mainElement = hapModuleInfo.mainAbility;
for (auto abilityInfo : hapModuleInfo.abilityInfos) {
if (abilityInfo.process == processName && abilityInfo.name == mainElement) {
return true;
}
}
return false;
}
// new application model
if (hapModuleInfo.process == processName) {
mainElement = hapModuleInfo.mainElementName;
return true;
}
return false;
};
auto GetKeepAliveAbilities = [&](std::vector<std::pair<std::string, std::string>> &keepAliveAbilities) {
for (size_t i = 0; i < bundleInfos.size(); i++) {
std::string processName = bundleInfos[i].applicationInfo.process;
if (!bundleInfos[i].isKeepAlive || processName.empty()) {
continue;
}
std::string bundleName = bundleInfos[i].name;
for (auto hapModuleInfo : bundleInfos[i].hapModuleInfos) {
std::string mainElement;
if (CheckIsAbilityKeepAlive(hapModuleInfo, processName, mainElement) && !mainElement.empty()) {
keepAliveAbilities.push_back(std::make_pair(bundleName, mainElement));
}
}
}
};
auto findKeepAliveAbility = [abilityRecord](const std::pair<std::string, std::string> &keepAlivePair) {
return ((abilityRecord->GetAbilityInfo().bundleName == keepAlivePair.first &&
abilityRecord->GetAbilityInfo().name == keepAlivePair.second) ||
abilityRecord->GetAbilityInfo().name == AbilityConfig::SYSTEM_UI_ABILITY_NAME ||
abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME);
};
std::vector<std::pair<std::string, std::string>> keepAliveAbilities;
GetKeepAliveAbilities(keepAliveAbilities);
auto findIter = find_if(keepAliveAbilities.begin(), keepAliveAbilities.end(), findKeepAliveAbility);
return (findIter != keepAliveAbilities.end());
}
void AbilityConnectManager::HandleAbilityDiedTask(
const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
{
HILOG_INFO("Handle ability died task.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
CHECK_POINTER(abilityRecord);
if (!GetServiceRecordByToken(abilityRecord->GetToken())) {
HILOG_ERROR("Died ability record is not exist in service map.");
return;
}
ConnectListType connlist = abilityRecord->GetConnectRecordList();
for (auto &connectRecord : connlist) {
HILOG_WARN("This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId());
connectRecord->CompleteDisconnect(ERR_OK, true);
abilityRecord->RemoveConnectRecordFromList(connectRecord);
RemoveConnectionRecordFromMap(connectRecord);
}
if (IsAbilityNeedRestart(abilityRecord)) {
HILOG_INFO("restart ability: %{public}s", abilityRecord->GetAbilityInfo().name.c_str());
AbilityRequest requestInfo;
requestInfo.want = abilityRecord->GetWant();
requestInfo.abilityInfo = abilityRecord->GetAbilityInfo();
requestInfo.appInfo = abilityRecord->GetApplicationInfo();
requestInfo.restart = true;
RemoveServiceAbility(abilityRecord);
if (currentUserId != userId_ &&
abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
HILOG_WARN("delay restart root launcher until switch user.");
return;
}
if (abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) {
requestInfo.restartCount = abilityRecord->GetRestartCount() - 1;
HILOG_DEBUG("restart root launcher, number:%{public}d", requestInfo.restartCount);
}
StartAbilityLocked(requestInfo);
return;
}
RemoveServiceAbility(abilityRecord);
}
void AbilityConnectManager::DumpState(std::vector<std::string> &info, bool isClient, const std::string &args) const
{
HILOG_INFO("DumpState args:%{public}s.", args.c_str());
if (!args.empty()) {
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 + " ]");
it->second->DumpService(info, isClient);
} else {
info.emplace_back(args + ": Nothing to dump.");
}
} else {
auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
info.emplace_back(" ExtensionRecords:");
for (auto &&service : serviceMap_) {
info.emplace_back(" uri [" + service.first + "]");
service.second->DumpService(info, isClient);
}
}
}
void AbilityConnectManager::DumpStateByUri(std::vector<std::string> &info, bool isClient, const std::string &args,
std::vector<std::string> &params) const
{
HILOG_INFO("DumpState args:%{public}s, params size: %{public}zu", args.c_str(), params.size());
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 + " ]");
it->second->DumpService(info, params, isClient);
} else {
info.emplace_back(args + ": Nothing to dump.");
}
}
void AbilityConnectManager::GetExtensionRunningInfos(int upperLimit, std::vector<ExtensionRunningInfo> &info,
const int32_t userId, bool isPerm)
{
HILOG_INFO("Get extension running info.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto mgr = shared_from_this();
auto queryInfo = [&info, upperLimit, userId, isPerm, mgr](ServiceMapType::reference service) {
if (static_cast<int>(info.size()) >= upperLimit) {
return;
}
auto abilityRecord = service.second;
CHECK_POINTER(abilityRecord);
if (isPerm) {
mgr->GetExtensionRunningInfo(abilityRecord, userId, info);
} else {
auto callingTokenId = IPCSkeleton::GetCallingTokenID();
auto tokenID = abilityRecord->GetApplicationInfo().accessTokenId;
if (callingTokenId == tokenID) {
mgr->GetExtensionRunningInfo(abilityRecord, userId, info);
}
}
};
std::for_each(serviceMap_.begin(), serviceMap_.end(), queryInfo);
}
void AbilityConnectManager::GetAbilityRunningInfos(std::vector<AbilityRunningInfo> &info, bool isPerm)
{
HILOG_INFO("Query running ability infos.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
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(serviceMap_.begin(), serviceMap_.end(), queryInfo);
}
void AbilityConnectManager::GetExtensionRunningInfo(std::shared_ptr<AbilityRecord> &abilityRecord, const int32_t userId,
std::vector<ExtensionRunningInfo> &info)
{
ExtensionRunningInfo extensionInfo;
AppExecFwk::RunningProcessInfo processInfo;
extensionInfo.extension = abilityRecord->GetWant().GetElement();
auto bms = AbilityUtil::GetBundleManager();
CHECK_POINTER(bms);
std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
bool queryResult = IN_PROCESS_CALL(bms->QueryExtensionAbilityInfos(abilityRecord->GetWant(),
AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, userId, extensionInfos));
if (queryResult) {
HILOG_INFO("Query Extension Ability Infos Success.");
auto abilityInfo = abilityRecord->GetAbilityInfo();
auto isExist = [&abilityInfo](const AppExecFwk::ExtensionAbilityInfo &extensionInfo) {
HILOG_INFO("%{public}s, %{public}s", extensionInfo.bundleName.c_str(), extensionInfo.name.c_str());
return extensionInfo.bundleName == abilityInfo.bundleName && extensionInfo.name == abilityInfo.name
&& extensionInfo.applicationInfo.uid == abilityInfo.applicationInfo.uid;
};
auto infoIter = std::find_if(extensionInfos.begin(), extensionInfos.end(), isExist);
if (infoIter != extensionInfos.end()) {
HILOG_INFO("Get target success.");
extensionInfo.type = (*infoIter).type;
}
}
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) {
CHECK_POINTER(connectRecord);
auto callerAbilityRecord = Token::GetAbilityRecordByToken(connectRecord->GetToken());
CHECK_POINTER(callerAbilityRecord);
std::string package = callerAbilityRecord->GetAbilityInfo().bundleName;
extensionInfo.clientPackage.emplace_back(package);
}
info.emplace_back(extensionInfo);
}
void AbilityConnectManager::StopAllExtensions()
{
HILOG_INFO("StopAllExtensions begin.");
std::lock_guard<std::recursive_mutex> guard(Lock_);
auto mgr = shared_from_this();
auto task = [mgr](ServiceMapType::reference service) {
auto abilityRecord = service.second;
CHECK_POINTER(abilityRecord);
if (abilityRecord->GetAbilityInfo().type == AbilityType::EXTENSION) {
mgr->TerminateAbilityLocked(abilityRecord->GetToken());
}
};
std::for_each(serviceMap_.begin(), serviceMap_.end(), task);
HILOG_INFO("StopAllExtensions end.");
}
} // namespace AAFwk
} // namespace OHOS