mirror of
https://github.com/openharmony/aafwk_standard.git
synced 2026-07-01 20:04:39 -04:00
83c84f8520
Description:无UI界面编译宏优化整改 Sig:SIG_ApplicationFramework Feature or Bugfix:Feature Binary Source: No Signed-off-by: dy_study <dingyao5@huawei.com> Change-Id: I4b7b7970263d7603791f2b1370a4eaf577f1a2b9
2933 lines
108 KiB
C++
2933 lines
108 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 "mission_list_manager.h"
|
||
|
||
#include "ability_manager_errors.h"
|
||
#include "ability_manager_service.h"
|
||
#include "ability_util.h"
|
||
#include "hitrace_meter.h"
|
||
#include "errors.h"
|
||
#include "hilog_wrapper.h"
|
||
#include "hisysevent.h"
|
||
#include "mission_info_mgr.h"
|
||
#ifdef SUPPORT_GRAPHICS
|
||
#include "image_source.h"
|
||
#include "in_process_call_wrapper.h"
|
||
#endif
|
||
|
||
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";
|
||
constexpr uint32_t NEXTABILITY_TIMEOUT = 1000; // ms
|
||
constexpr uint64_t NANO_SECOND_PER_SEC = 1000000000; // ns
|
||
const std::string SHOW_ON_LOCK_SCREEN = "ShowOnLockScreen";
|
||
std::string GetCurrentTime()
|
||
{
|
||
struct timespec tn;
|
||
clock_gettime(CLOCK_REALTIME, &tn);
|
||
uint64_t uTime = static_cast<uint64_t>(tn.tv_sec) * NANO_SECOND_PER_SEC + tn.tv_nsec;
|
||
return std::to_string(uTime);
|
||
}
|
||
} // namespace
|
||
|
||
MissionListManager::MissionListManager(int userId) : userId_(userId) {}
|
||
|
||
MissionListManager::~MissionListManager() {}
|
||
|
||
void MissionListManager::Init()
|
||
{
|
||
launcherList_ = std::make_shared<MissionList>(MissionListType::LAUNCHER);
|
||
defaultStandardList_ = std::make_shared<MissionList>(MissionListType::DEFAULT_STANDARD);
|
||
defaultSingleList_ = std::make_shared<MissionList>(MissionListType::DEFAULT_SINGLE);
|
||
currentMissionLists_.push_front(launcherList_);
|
||
|
||
if (!listenerController_) {
|
||
listenerController_ = std::make_shared<MissionListenerController>();
|
||
listenerController_->Init();
|
||
}
|
||
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->Init(userId_);
|
||
}
|
||
|
||
int MissionListManager::StartAbility(const AbilityRequest &abilityRequest)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto currentTopAbility = GetCurrentTopAbilityLocked();
|
||
if (currentTopAbility) {
|
||
std::string element = currentTopAbility->GetWant().GetElement().GetURI();
|
||
auto state = currentTopAbility->GetAbilityState();
|
||
HILOG_DEBUG("current top: %{public}s, state: %{public}s",
|
||
element.c_str(), AbilityRecord::ConvertAbilityState(state).c_str());
|
||
if (state == FOREGROUNDING) {
|
||
HILOG_INFO("Top ability is foregrounding, so enqueue ability for waiting.");
|
||
EnqueueWaittingAbility(abilityRequest);
|
||
return START_ABILITY_WAITING;
|
||
}
|
||
}
|
||
|
||
auto callerAbility = GetAbilityRecordByToken(abilityRequest.callerToken);
|
||
if (callerAbility) {
|
||
std::string element = callerAbility->GetWant().GetElement().GetURI();
|
||
auto state = callerAbility->GetAbilityState();
|
||
HILOG_DEBUG("callerAbility is: %{public}s, state: %{public}s",
|
||
element.c_str(), AbilityRecord::ConvertAbilityState(state).c_str());
|
||
}
|
||
|
||
return StartAbility(currentTopAbility, callerAbility, abilityRequest);
|
||
}
|
||
|
||
int MissionListManager::StartAbility(const std::shared_ptr<AbilityRecord> ¤tTopAbility,
|
||
const std::shared_ptr<AbilityRecord> &callerAbility, const AbilityRequest &abilityRequest)
|
||
{
|
||
auto isSpecified = (abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SPECIFIED);
|
||
if (isSpecified) {
|
||
EnqueueWaittingAbilityToFront(abilityRequest);
|
||
DelayedSingleton<AppScheduler>::GetInstance()->StartSpecifiedAbility(
|
||
abilityRequest.want, abilityRequest.abilityInfo);
|
||
return 0;
|
||
}
|
||
|
||
return StartAbilityLocked(currentTopAbility, callerAbility, abilityRequest);
|
||
}
|
||
|
||
int MissionListManager::MinimizeAbility(const sptr<IRemoteObject> &token, bool fromUser)
|
||
{
|
||
HILOG_INFO("Minimize ability, fromUser:%{public}d.", fromUser);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
// check if ability is in list to avoid user create fake token.
|
||
CHECK_POINTER_AND_RETURN_LOG(
|
||
GetAbilityRecordByToken(token), INNER_ERR, "Minimize ability fail, ability is not in mission list.");
|
||
auto abilityRecord = Token::GetAbilityRecordByToken(token);
|
||
return MinimizeAbilityLocked(abilityRecord, fromUser);
|
||
}
|
||
|
||
int MissionListManager::RegisterMissionListener(const sptr<IMissionListener> &listener)
|
||
{
|
||
if (!listenerController_) {
|
||
HILOG_ERROR("service not init, try again later.");
|
||
return -1;
|
||
}
|
||
|
||
return listenerController_->AddMissionListener(listener);
|
||
}
|
||
|
||
int MissionListManager::UnRegisterMissionListener(const sptr<IMissionListener> &listener)
|
||
{
|
||
if (!listenerController_) {
|
||
HILOG_ERROR("service not init, try unregister again later.");
|
||
return -1;
|
||
}
|
||
|
||
listenerController_->DelMissionListener(listener);
|
||
return 0;
|
||
}
|
||
|
||
int MissionListManager::GetMissionInfos(int32_t numMax, std::vector<MissionInfo> &missionInfos)
|
||
{
|
||
HILOG_INFO("Get mission infos.");
|
||
if (numMax < 0) {
|
||
HILOG_ERROR("numMax is invalid, numMax:%{public}d", numMax);
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
return DelayedSingleton<MissionInfoMgr>::GetInstance()->GetMissionInfos(numMax, missionInfos);
|
||
}
|
||
|
||
int MissionListManager::GetMissionInfo(int32_t missionId, MissionInfo &missionInfo)
|
||
{
|
||
HILOG_INFO("Get mission info by id:%{public}d.", missionId);
|
||
return DelayedSingleton<MissionInfoMgr>::GetInstance()->GetMissionInfoById(missionId, missionInfo);
|
||
}
|
||
|
||
int MissionListManager::MoveMissionToFront(int32_t missionId, std::shared_ptr<StartOptions> startOptions)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
return MoveMissionToFront(missionId, true, startOptions);
|
||
}
|
||
|
||
int MissionListManager::MoveMissionToFront(int32_t missionId, bool isCallerFromLauncher,
|
||
std::shared_ptr<StartOptions> startOptions)
|
||
{
|
||
HILOG_INFO("move mission to front:%{public}d.", missionId);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
std::shared_ptr<Mission> mission;
|
||
bool isCold = false;
|
||
auto targetMissionList = GetTargetMissionList(missionId, mission, isCold);
|
||
if (!targetMissionList || !mission) {
|
||
HILOG_ERROR("get target mission list failed, missionId: %{public}d", missionId);
|
||
return MOVE_MISSION_FAILED;
|
||
}
|
||
|
||
MoveMissionToTargetList(isCallerFromLauncher, targetMissionList, mission);
|
||
MoveMissionListToTop(targetMissionList);
|
||
|
||
auto targetAbilityRecord = mission->GetAbilityRecord();
|
||
if (!targetAbilityRecord) {
|
||
HILOG_ERROR("get target ability record failed, missionId: %{public}d", missionId);
|
||
return MOVE_MISSION_FAILED;
|
||
}
|
||
targetAbilityRecord->RemoveWindowMode();
|
||
if (startOptions != nullptr) {
|
||
targetAbilityRecord->SetWindowMode(startOptions->GetWindowMode());
|
||
}
|
||
|
||
#ifdef SUPPORT_GRAPHICS
|
||
NotifyStartingWindow(isCold, targetAbilityRecord, startOptions, missionId);
|
||
#endif
|
||
|
||
// schedule target ability to foreground.
|
||
targetAbilityRecord->ProcessForegroundAbility();
|
||
HILOG_DEBUG("SetMovingState, missionId: %{public}d", missionId);
|
||
mission->SetMovingState(true);
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::EnqueueWaittingAbility(const AbilityRequest &abilityRequest)
|
||
{
|
||
waittingAbilityQueue_.push(abilityRequest);
|
||
return;
|
||
}
|
||
|
||
void MissionListManager::EnqueueWaittingAbilityToFront(const AbilityRequest &abilityRequest)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
std::queue<AbilityRequest> abilityQueue;
|
||
abilityQueue.push(abilityRequest);
|
||
waittingAbilityQueue_.swap(abilityQueue);
|
||
while (!abilityQueue.empty()) {
|
||
AbilityRequest tempAbilityRequest = abilityQueue.front();
|
||
abilityQueue.pop();
|
||
waittingAbilityQueue_.push(tempAbilityRequest);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::StartWaittingAbility()
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto topAbility = GetCurrentTopAbilityLocked();
|
||
CHECK_POINTER(topAbility);
|
||
|
||
if (!topAbility->IsAbilityState(FOREGROUND)) {
|
||
HILOG_INFO("Top ability is not foreground new, must return for start waiting again.");
|
||
return;
|
||
}
|
||
|
||
if (!waittingAbilityQueue_.empty()) {
|
||
AbilityRequest abilityRequest = waittingAbilityQueue_.front();
|
||
waittingAbilityQueue_.pop();
|
||
auto callerAbility = GetAbilityRecordByToken(abilityRequest.callerToken);
|
||
StartAbility(topAbility, callerAbility, abilityRequest);
|
||
return;
|
||
}
|
||
}
|
||
|
||
int MissionListManager::StartAbilityLocked(const std::shared_ptr<AbilityRecord> ¤tTopAbility,
|
||
const std::shared_ptr<AbilityRecord> &callerAbility, const AbilityRequest &abilityRequest)
|
||
{
|
||
HILOG_DEBUG("Start ability locked.");
|
||
// 1. choose target mission list
|
||
auto targetList = GetTargetMissionList(callerAbility, abilityRequest);
|
||
CHECK_POINTER_AND_RETURN(targetList, CREATE_MISSION_STACK_FAILED);
|
||
|
||
// 2. get target mission
|
||
std::shared_ptr<AbilityRecord> targetAbilityRecord;
|
||
std::shared_ptr<Mission> targetMission;
|
||
bool isCold = false;
|
||
GetTargetMissionAndAbility(abilityRequest, targetMission, targetAbilityRecord, isCold);
|
||
if (!targetMission || !targetAbilityRecord) {
|
||
HILOG_ERROR("Failed to get mission or record.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
if (abilityRequest.IsContinuation()) {
|
||
targetAbilityRecord->SetLaunchReason(LaunchReason::LAUNCHREASON_CONTINUATION);
|
||
} else {
|
||
targetAbilityRecord->SetLaunchReason(LaunchReason::LAUNCHREASON_START_ABILITY);
|
||
}
|
||
targetAbilityRecord->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode);
|
||
|
||
// 3. move mission to target list
|
||
bool isCallerFromLauncher = (callerAbility && callerAbility->IsLauncherAbility());
|
||
MoveMissionToTargetList(isCallerFromLauncher, targetList, targetMission);
|
||
|
||
// 4. move target list to top
|
||
MoveMissionListToTop(targetList);
|
||
|
||
#ifdef SUPPORT_GRAPHICS
|
||
NotifyStartingWindow(isCold, targetMission, targetAbilityRecord, abilityRequest, callerAbility);
|
||
#endif
|
||
|
||
// 5. schedule target ability
|
||
if (!currentTopAbility) {
|
||
// top ability is null, then launch the first Ability.
|
||
if (targetAbilityRecord->GetAbilityInfo().applicationInfo.isLauncherApp) {
|
||
targetAbilityRecord->SetLauncherRoot();
|
||
}
|
||
return targetAbilityRecord->LoadAbility();
|
||
} else {
|
||
// schedule target ability to foreground.
|
||
targetAbilityRecord->ProcessForegroundAbility();
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static int32_t CallType2StartMethod(int32_t callType)
|
||
{
|
||
switch (callType) {
|
||
case AbilityCallType::INVALID_TYPE:
|
||
return static_cast<int32_t>(StartMethod::START_NORMAL);
|
||
case AbilityCallType::CALL_REQUEST_TYPE:
|
||
return static_cast<int32_t>(StartMethod::START_CALL);
|
||
default:
|
||
break;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
static bool CallTypeFilter(int32_t callType)
|
||
{
|
||
switch (callType) {
|
||
case AbilityCallType::CALL_REQUEST_TYPE:
|
||
return true;
|
||
default:
|
||
break;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void MissionListManager::GetTargetMissionAndAbility(const AbilityRequest &abilityRequest,
|
||
std::shared_ptr<Mission> &targetMission, std::shared_ptr<AbilityRecord> &targetRecord, bool &isCold)
|
||
{
|
||
auto startMethod = CallType2StartMethod(abilityRequest.callType);
|
||
HILOG_DEBUG("GetTargetMissionAndAbility called startMethod is %{public}d.", startMethod);
|
||
auto reUsedMission = GetReusedMission(abilityRequest);
|
||
if (reUsedMission) {
|
||
HILOG_DEBUG("find reused mission in running list.");
|
||
targetMission = reUsedMission;
|
||
targetRecord = targetMission->GetAbilityRecord();
|
||
if (targetRecord) {
|
||
targetRecord->SetWant(abilityRequest.want);
|
||
targetRecord->SetIsNewWant(true);
|
||
}
|
||
|
||
if (!(targetMission->IsStartByCall()
|
||
&& !CallTypeFilter(startMethod))) {
|
||
HILOG_DEBUG("mission exists. No update required");
|
||
return;
|
||
}
|
||
HILOG_DEBUG("mission exists. need to be updated");
|
||
}
|
||
|
||
// no reused mission, create a new one.
|
||
bool isSingleton = abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SINGLETON;
|
||
std::string missionName = isSingleton ? AbilityUtil::ConvertBundleNameSingleton(
|
||
abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name) : abilityRequest.abilityInfo.bundleName;
|
||
|
||
// try reuse mission info
|
||
InnerMissionInfo info;
|
||
bool findReusedMissionInfo = false;
|
||
if (isSingleton && !abilityRequest.abilityInfo.applicationInfo.isLauncherApp) {
|
||
findReusedMissionInfo =
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->FindReusedSingletonMission(missionName, info);
|
||
}
|
||
findReusedMissionInfo = (findReusedMissionInfo && info.missionInfo.id > 0);
|
||
HILOG_INFO("try find reused mission info. result:%{public}d", findReusedMissionInfo);
|
||
|
||
info.missionName = missionName;
|
||
info.isSingletonMode = isSingleton;
|
||
info.startMethod = startMethod;
|
||
info.bundleName = abilityRequest.abilityInfo.bundleName;
|
||
info.uid = abilityRequest.uid;
|
||
info.missionInfo.runningState = 0;
|
||
info.missionInfo.continuable = abilityRequest.abilityInfo.continuable;
|
||
info.missionInfo.time = GetCurrentTime();
|
||
info.missionInfo.iconPath = abilityRequest.appInfo.iconPath;
|
||
info.missionInfo.want = abilityRequest.want;
|
||
|
||
if (!findReusedMissionInfo) {
|
||
info.missionInfo.label = abilityRequest.appInfo.label;
|
||
if (!DelayedSingleton<MissionInfoMgr>::GetInstance()->GenerateMissionId(info.missionInfo.id)) {
|
||
HILOG_DEBUG("failed to generate mission id.");
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (targetMission == nullptr) {
|
||
HILOG_DEBUG("Make new mission data.");
|
||
targetRecord = AbilityRecord::CreateAbilityRecord(abilityRequest);
|
||
isCold = true;
|
||
targetMission = std::make_shared<Mission>(info.missionInfo.id, targetRecord, missionName, startMethod);
|
||
targetRecord->SetMission(targetMission);
|
||
} else {
|
||
HILOG_DEBUG("Update old mission data.");
|
||
auto state = targetMission->UpdateMissionId(info.missionInfo.id, startMethod);
|
||
if (!state) {
|
||
HILOG_INFO("targetMission UpdateMissionId(%{public}d, %{public}d) failed", info.missionInfo.id,
|
||
startMethod);
|
||
}
|
||
HILOG_DEBUG("Update MissionId UpdateMissionId(%{public}d, %{public}d) end", info.missionInfo.id, startMethod);
|
||
}
|
||
|
||
if (abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SPECIFIED) {
|
||
targetRecord->SetSpecifiedFlag(abilityRequest.specifiedFlag);
|
||
}
|
||
|
||
if (abilityRequest.abilityInfo.applicationInfo.isLauncherApp) {
|
||
return;
|
||
}
|
||
|
||
if (findReusedMissionInfo) {
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(info);
|
||
} else {
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->AddMissionInfo(info);
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionCreated(info.missionInfo.id);
|
||
}
|
||
}
|
||
}
|
||
|
||
std::shared_ptr<MissionList> MissionListManager::GetTargetMissionList(
|
||
const std::shared_ptr<AbilityRecord> &callerAbility, const AbilityRequest &abilityRequest)
|
||
{
|
||
// priority : starting launcher ability.
|
||
if (abilityRequest.abilityInfo.applicationInfo.isLauncherApp) {
|
||
HILOG_DEBUG("ability reques is launcher app.");
|
||
return launcherList_;
|
||
}
|
||
|
||
// no caller ability, start ability from system service.
|
||
if (!callerAbility) {
|
||
HILOG_DEBUG("ability reques without caller.");
|
||
std::shared_ptr<MissionList> targetMissionList = std::make_shared<MissionList>();
|
||
return targetMissionList;
|
||
}
|
||
|
||
// caller is launcher, new or reuse list.
|
||
if (callerAbility->IsLauncherAbility()) {
|
||
HILOG_DEBUG("start ability, caller is launcher app.");
|
||
return GetTargetMissionListByLauncher(abilityRequest);
|
||
}
|
||
|
||
// caller is not launcher: refer to the list of the caller ability.
|
||
return GetTargetMissionListByDefault(callerAbility, abilityRequest);
|
||
}
|
||
|
||
std::shared_ptr<MissionList> MissionListManager::GetTargetMissionListByLauncher(const AbilityRequest &abilityRequest)
|
||
{
|
||
auto reUsedMission = GetReusedMission(abilityRequest);
|
||
if (reUsedMission) {
|
||
HILOG_DEBUG("GetTargetMissionListByLauncher find reused mission list.");
|
||
auto missionList = reUsedMission->GetMissionList();
|
||
if (missionList && missionList != defaultSingleList_ && missionList != defaultStandardList_) {
|
||
return missionList;
|
||
}
|
||
}
|
||
|
||
HILOG_DEBUG("GetTargetMissionListByLauncher do not find reused mission list.");
|
||
std::shared_ptr<MissionList> targetMissionList = std::make_shared<MissionList>();
|
||
return targetMissionList;
|
||
}
|
||
|
||
std::shared_ptr<MissionList> MissionListManager::GetTargetMissionListByDefault(
|
||
const std::shared_ptr<AbilityRecord> &callerAbility, const AbilityRequest &abilityRequest)
|
||
{
|
||
if (!callerAbility) {
|
||
return nullptr;
|
||
}
|
||
|
||
auto callerMission = callerAbility->GetMission();
|
||
auto callerList = callerAbility->GetOwnedMissionList();
|
||
if (!callerMission || !callerList) {
|
||
return nullptr; // invalid status
|
||
}
|
||
|
||
// target mission should in caller mission list
|
||
if (callerList != defaultStandardList_ && callerList != defaultSingleList_) {
|
||
HILOG_DEBUG("GetTargetMissionListByDefault target is cller list.");
|
||
return callerList;
|
||
}
|
||
|
||
// caller is default, need to start a new mission list
|
||
HILOG_DEBUG("GetTargetMissionListByDefault target is default list.");
|
||
std::shared_ptr<MissionList> targetMissionList = std::make_shared<MissionList>();
|
||
callerList->RemoveMission(callerMission);
|
||
targetMissionList->AddMissionToTop(callerMission);
|
||
|
||
return targetMissionList;
|
||
}
|
||
|
||
std::shared_ptr<Mission> MissionListManager::GetReusedMission(const AbilityRequest &abilityRequest)
|
||
{
|
||
if (abilityRequest.abilityInfo.launchMode != AppExecFwk::LaunchMode::SINGLETON) {
|
||
return nullptr;
|
||
}
|
||
|
||
std::shared_ptr<Mission> reUsedMission = nullptr;
|
||
std::string missionName = AbilityUtil::ConvertBundleNameSingleton(abilityRequest.abilityInfo.bundleName,
|
||
abilityRequest.abilityInfo.name);
|
||
|
||
// find launcher first.
|
||
if (abilityRequest.abilityInfo.applicationInfo.isLauncherApp) {
|
||
if ((reUsedMission = launcherList_->GetSingletonMissionByName(missionName)) != nullptr) {
|
||
return reUsedMission;
|
||
}
|
||
}
|
||
|
||
// current
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (reUsedMission = missionList->GetSingletonMissionByName(missionName)) != nullptr) {
|
||
return reUsedMission;
|
||
}
|
||
}
|
||
|
||
// default single list
|
||
if ((reUsedMission = defaultSingleList_->GetSingletonMissionByName(missionName)) != nullptr) {
|
||
return reUsedMission;
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
void MissionListManager::MoveMissionToTargetList(bool isCallFromLauncher,
|
||
const std::shared_ptr<MissionList> &targetMissionList,
|
||
const std::shared_ptr<Mission> &mission)
|
||
{
|
||
auto missionList = mission->GetMissionList();
|
||
// 1. new mission,move to target list.
|
||
if (!missionList) {
|
||
targetMissionList->AddMissionToTop(mission);
|
||
return;
|
||
}
|
||
|
||
// 2. launcher call launcher
|
||
if (isCallFromLauncher && targetMissionList == launcherList_) {
|
||
targetMissionList->AddMissionToTop(mission);
|
||
return;
|
||
}
|
||
|
||
// 3. reused mission is in default, move frome default to target list.
|
||
if (missionList == defaultSingleList_ || missionList == defaultStandardList_) {
|
||
missionList->RemoveMission(mission);
|
||
targetMissionList->AddMissionToTop(mission);
|
||
return;
|
||
}
|
||
|
||
// 4. reused mission is in a valid list.
|
||
bool isListChange = !(targetMissionList == missionList);
|
||
if (isListChange) {
|
||
// list change, pop above missions to default.
|
||
MoveNoneTopMissionToDefaultList(mission);
|
||
missionList->RemoveMission(mission);
|
||
} else if (isCallFromLauncher) {
|
||
// list not change, but call from launcher, pop above missions to default.
|
||
MoveNoneTopMissionToDefaultList(mission);
|
||
}
|
||
targetMissionList->AddMissionToTop(mission);
|
||
|
||
if (missionList->IsEmpty()) {
|
||
currentMissionLists_.remove(missionList);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::MoveNoneTopMissionToDefaultList(const std::shared_ptr<Mission> &mission)
|
||
{
|
||
auto missionList = mission->GetMissionList();
|
||
if (!missionList) {
|
||
return;
|
||
}
|
||
|
||
while (!missionList->IsEmpty()) {
|
||
auto item = missionList->GetTopMission();
|
||
if (item == nullptr || item == mission) {
|
||
break;
|
||
}
|
||
|
||
missionList->RemoveMission(item);
|
||
if (item->IsSingletonAbility()) {
|
||
defaultSingleList_->AddMissionToTop(item);
|
||
} else {
|
||
defaultStandardList_->AddMissionToTop(item);
|
||
}
|
||
}
|
||
}
|
||
|
||
void MissionListManager::MoveMissionListToTop(const std::shared_ptr<MissionList> &missionList)
|
||
{
|
||
if (!missionList) {
|
||
HILOG_ERROR("mission list is nullptr.");
|
||
return;
|
||
}
|
||
if (!currentMissionLists_.empty() && currentMissionLists_.front() == missionList) {
|
||
HILOG_DEBUG("mission list is at the top of list");
|
||
return;
|
||
}
|
||
|
||
currentMissionLists_.remove(missionList);
|
||
currentMissionLists_.push_front(missionList);
|
||
}
|
||
|
||
int MissionListManager::MinimizeAbilityLocked(const std::shared_ptr<AbilityRecord> &abilityRecord, bool fromUser)
|
||
{
|
||
if (abilityRecord == nullptr) {
|
||
HILOG_ERROR("Minimize ability fail, ability record is null.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
HILOG_INFO("%{public}s called, ability:%{public}s.", __func__, abilityRecord->GetAbilityInfo().name.c_str());
|
||
|
||
if (!abilityRecord->IsAbilityState(AbilityState::FOREGROUND) &&
|
||
!abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
||
HILOG_ERROR("Minimize ability fail, ability state is invalid, not foregroundnew or foregerounding_new.");
|
||
return ERR_OK;
|
||
}
|
||
|
||
abilityRecord->SetMinimizeReason(fromUser);
|
||
MoveToBackgroundTask(abilityRecord);
|
||
UpdateMissionTimeStamp(abilityRecord);
|
||
return ERR_OK;
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetCurrentTopAbilityLocked() const
|
||
{
|
||
if (currentMissionLists_.empty()) {
|
||
return nullptr;
|
||
}
|
||
|
||
auto& topMissionList = currentMissionLists_.front();
|
||
if (topMissionList) {
|
||
return topMissionList->GetTopAbility();
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
int MissionListManager::AttachAbilityThread(const sptr<IAbilityScheduler> &scheduler, const sptr<IRemoteObject> &token)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityRecordByToken(token);
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
||
|
||
HILOG_DEBUG("AbilityMS attch abilityThread, name is %{public}s.", abilityRecord->GetAbilityInfo().name.c_str());
|
||
|
||
std::shared_ptr<AbilityEventHandler> handler =
|
||
DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler.");
|
||
handler->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId());
|
||
#ifdef SUPPORT_GRAPHICS
|
||
abilityRecord->SetStartingWindow(false);
|
||
#endif
|
||
|
||
abilityRecord->SetScheduler(scheduler);
|
||
|
||
if (abilityRecord->IsStartedByCall()) {
|
||
// started by callability, directly move to background.
|
||
abilityRecord->SetStartToBackground(true);
|
||
MoveToBackgroundTask(abilityRecord);
|
||
return ERR_OK;
|
||
}
|
||
|
||
if (abilityRecord->IsNeedToCallRequest()) {
|
||
abilityRecord->CallRequest();
|
||
}
|
||
|
||
DelayedSingleton<AppScheduler>::GetInstance()->MoveToForground(token);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::OnAbilityRequestDone(const sptr<IRemoteObject> &token, const int32_t state)
|
||
{
|
||
HILOG_DEBUG("Ability request state %{public}d done.", state);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
AppAbilityState abilitState = DelayedSingleton<AppScheduler>::GetInstance()->ConvertToAppAbilityState(state);
|
||
if (abilitState == AppAbilityState::ABILITY_STATE_FOREGROUND) {
|
||
auto abilityRecord = GetAbilityRecordByToken(token);
|
||
CHECK_POINTER(abilityRecord);
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("Ability is %{public}s, start to foreground.", element.c_str());
|
||
abilityRecord->ForegroundAbility(abilityRecord->lifeCycleStateInfo_.sceneFlagBak);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::OnAppStateChanged(const AppInfo &info)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
if (info.state == AppState::TERMINATED || info.state == AppState::END) {
|
||
for (const auto& abilityRecord : terminateAbilityList_) {
|
||
if (!abilityRecord) {
|
||
HILOG_ERROR("abilityRecord is nullptr.");
|
||
continue;
|
||
}
|
||
if (info.processName == abilityRecord->GetAbilityInfo().process ||
|
||
info.processName == abilityRecord->GetApplicationInfo().bundleName) {
|
||
abilityRecord->SetAppState(info.state);
|
||
}
|
||
}
|
||
} else {
|
||
for (const auto& missionList : currentMissionLists_) {
|
||
auto missions = missionList->GetAllMissions();
|
||
for (const auto& missionInfo : missions) {
|
||
if (!missionInfo) {
|
||
HILOG_ERROR("missionInfo is nullptr.");
|
||
continue;
|
||
}
|
||
auto abilityRecord = missionInfo->GetAbilityRecord();
|
||
if (info.processName == abilityRecord->GetAbilityInfo().process ||
|
||
info.processName == abilityRecord->GetApplicationInfo().bundleName) {
|
||
abilityRecord->SetAppState(info.state);
|
||
}
|
||
}
|
||
}
|
||
auto defaultStandardListmissions = defaultStandardList_->GetAllMissions();
|
||
for (const auto& missionInfo : defaultStandardListmissions) {
|
||
if (!missionInfo) {
|
||
HILOG_ERROR("defaultStandardListmissions is nullptr.");
|
||
continue;
|
||
}
|
||
auto abilityRecord = missionInfo->GetAbilityRecord();
|
||
if (info.processName == abilityRecord->GetAbilityInfo().process ||
|
||
info.processName == abilityRecord->GetApplicationInfo().bundleName) {
|
||
abilityRecord->SetAppState(info.state);
|
||
}
|
||
}
|
||
auto defaultSingleListmissions = defaultSingleList_->GetAllMissions();
|
||
for (const auto& missionInfo : defaultSingleListmissions) {
|
||
if (!missionInfo) {
|
||
HILOG_ERROR("defaultSingleListmissions is nullptr.");
|
||
continue;
|
||
}
|
||
auto abilityRecord = missionInfo->GetAbilityRecord();
|
||
if (info.processName == abilityRecord->GetAbilityInfo().process ||
|
||
info.processName == abilityRecord->GetApplicationInfo().bundleName) {
|
||
abilityRecord->SetAppState(info.state);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetAbilityRecordByToken(
|
||
const sptr<IRemoteObject> &token) const
|
||
{
|
||
if (!token) {
|
||
return nullptr;
|
||
}
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
// first find in terminating list
|
||
for (auto ability : terminateAbilityList_) {
|
||
if (ability && token == ability->GetToken()->AsObject()) {
|
||
return ability;
|
||
}
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> abilityRecord = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (abilityRecord = missionList->GetAbilityRecordByToken(token)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
}
|
||
|
||
if ((abilityRecord = defaultSingleList_->GetAbilityRecordByToken(token)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
|
||
return defaultStandardList_->GetAbilityRecordByToken(token);
|
||
}
|
||
|
||
std::shared_ptr<Mission> MissionListManager::GetMissionById(int missionId) const
|
||
{
|
||
std::shared_ptr<Mission> mission = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (mission = missionList->GetMissionById(missionId)) != nullptr) {
|
||
return mission;
|
||
}
|
||
}
|
||
|
||
if ((mission = defaultSingleList_->GetMissionById(missionId)) != nullptr) {
|
||
return mission;
|
||
}
|
||
|
||
if ((mission = launcherList_->GetMissionById(missionId)) != nullptr) {
|
||
return mission;
|
||
}
|
||
|
||
return defaultStandardList_->GetMissionById(missionId);
|
||
}
|
||
|
||
int MissionListManager::AbilityTransactionDone(const sptr<IRemoteObject> &token, int state, const PacMap &saveData)
|
||
{
|
||
int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast<AbilityLifeCycleState>(state));
|
||
std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast<AbilityState>(targetState));
|
||
HILOG_INFO("AbilityTransactionDone, state: %{public}s.", abilityState.c_str());
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityFromTerminateList(token);
|
||
if (abilityRecord == nullptr) {
|
||
abilityRecord = GetAbilityRecordByToken(token);
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
||
}
|
||
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_INFO("ability: %{public}s, state: %{public}s", element.c_str(), abilityState.c_str());
|
||
|
||
if (targetState == AbilityState::BACKGROUND) {
|
||
abilityRecord->SaveAbilityState(saveData);
|
||
}
|
||
|
||
return DispatchState(abilityRecord, targetState);
|
||
}
|
||
|
||
int MissionListManager::DispatchState(const std::shared_ptr<AbilityRecord> &abilityRecord, int state)
|
||
{
|
||
switch (state) {
|
||
case AbilityState::INITIAL: {
|
||
return DispatchTerminate(abilityRecord);
|
||
}
|
||
case AbilityState::BACKGROUND: {
|
||
return DispatchBackground(abilityRecord);
|
||
}
|
||
case AbilityState::FOREGROUND: {
|
||
return DispatchForegroundNew(abilityRecord);
|
||
}
|
||
default: {
|
||
HILOG_WARN("Don't support transiting state: %{public}d", state);
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
int MissionListManager::DispatchForegroundNew(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler.");
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
||
|
||
if (!abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
||
HILOG_ERROR("DispatchForegroundNew Ability transition life state error. expect %{public}d, actual %{public}d",
|
||
AbilityState::FOREGROUNDING,
|
||
abilityRecord->GetAbilityState());
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
handler->RemoveEvent(AbilityManagerService::FOREGROUNDNEW_TIMEOUT_MSG, abilityRecord->GetEventId());
|
||
auto self(shared_from_this());
|
||
auto task = [self, abilityRecord]() { self->CompleteForegroundNew(abilityRecord); };
|
||
handler->PostTask(task);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::CompleteForegroundNew(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
CHECK_POINTER(abilityRecord);
|
||
#ifdef SUPPORT_GRAPHICS
|
||
abilityRecord->SetStartingWindow(false);
|
||
#endif
|
||
// ability do not save window mode
|
||
abilityRecord->RemoveWindowMode();
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_INFO("ability: %{public}s", element.c_str());
|
||
|
||
abilityRecord->SetAbilityState(AbilityState::FOREGROUND);
|
||
|
||
DelayedSingleton<AbilityManagerService>::GetInstance()->NotifyBmsAbilityLifeStatus(
|
||
abilityRecord->GetAbilityInfo().bundleName,
|
||
abilityRecord->GetAbilityInfo().name,
|
||
AbilityUtil::UTCTimeSeconds(),
|
||
abilityRecord->GetApplicationInfo().uid);
|
||
#if BINDER_IPC_32BIT
|
||
HILOG_INFO("notify bms ability life status, bundle name:%{public}s, ability name:%{public}s, time:%{public}lld",
|
||
abilityRecord->GetAbilityInfo().bundleName.c_str(),
|
||
abilityRecord->GetAbilityInfo().name.c_str(),
|
||
AbilityUtil::UTCTimeSeconds());
|
||
#else
|
||
HILOG_INFO("notify bms ability life status, bundle name:%{public}s, ability name:%{public}s, time:%{public}ld",
|
||
abilityRecord->GetAbilityInfo().bundleName.c_str(),
|
||
abilityRecord->GetAbilityInfo().name.c_str(),
|
||
AbilityUtil::UTCTimeSeconds());
|
||
#endif
|
||
|
||
auto mission = abilityRecord->GetMission();
|
||
if (mission) {
|
||
InnerMissionInfo info;
|
||
if (DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
mission->GetMissionId(), info) == 0) {
|
||
info.missionInfo.time = GetCurrentTime();
|
||
info.missionInfo.runningState = 0;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(info);
|
||
}
|
||
}
|
||
|
||
if (mission && mission->IsMovingState()) {
|
||
mission->SetMovingState(false);
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionMovedToFront(mission->GetMissionId());
|
||
}
|
||
}
|
||
|
||
auto self(shared_from_this());
|
||
auto startWaittingAbilityTask = [self]() { self->StartWaittingAbility(); };
|
||
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_LOG(handler, "Fail to get AbilityEventHandler.");
|
||
|
||
/* PostTask to trigger start Ability from waiting queue */
|
||
handler->PostTask(startWaittingAbilityTask, "startWaittingAbility", NEXTABILITY_TIMEOUT);
|
||
}
|
||
|
||
int MissionListManager::DispatchBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler.");
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
||
|
||
if (!abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING)) {
|
||
HILOG_ERROR("Ability transition life state error. actual %{public}d", abilityRecord->GetAbilityState());
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
// remove background timeout task.
|
||
handler->RemoveTask(std::to_string(abilityRecord->GetEventId()));
|
||
auto self(shared_from_this());
|
||
auto task = [self, abilityRecord]() { self->CompleteBackground(abilityRecord); };
|
||
handler->PostTask(task);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::CompleteBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (abilityRecord->GetAbilityState() != AbilityState::BACKGROUNDING) {
|
||
HILOG_ERROR("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());
|
||
|
||
if (abilityRecord->IsSwitchingPause()) {
|
||
abilityRecord->SetSwitchingPause(false);
|
||
return;
|
||
}
|
||
|
||
// Abilities ahead of the one started with SingleTask mode were put in terminate list, we need to terminate
|
||
// them.
|
||
auto self(shared_from_this());
|
||
for (auto terminateAbility : terminateAbilityList_) {
|
||
if (terminateAbility->GetAbilityState() == AbilityState::BACKGROUND) {
|
||
auto timeoutTask = [terminateAbility, self]() {
|
||
HILOG_WARN("Disconnect ability terminate timeout.");
|
||
self->PrintTimeOutLog(terminateAbility, AbilityManagerService::TERMINATE_TIMEOUT_MSG);
|
||
self->CompleteTerminate(terminateAbility);
|
||
};
|
||
terminateAbility->Terminate(timeoutTask);
|
||
}
|
||
}
|
||
|
||
// new version. started by caller, sdheduler call request
|
||
if (abilityRecord->IsStartedByCall() && abilityRecord->IsStartToBackground() && abilityRecord->IsReady()) {
|
||
HILOG_DEBUG("call request after completing background state");
|
||
abilityRecord->CallRequest();
|
||
abilityRecord->SetStartToBackground(false);
|
||
}
|
||
}
|
||
|
||
int MissionListManager::TerminateAbility(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
||
int resultCode, const Want *resultWant, bool flag)
|
||
{
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("Terminate ability, ability is %{public}s.", element.c_str());
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (abilityRecord->IsTerminating() && !abilityRecord->IsForeground()) {
|
||
HILOG_ERROR("Ability is on terminating.");
|
||
return ERR_OK;
|
||
}
|
||
|
||
if (abilityRecord->IsTerminating() && abilityRecord->IsForeground()) {
|
||
HILOG_WARN("Ability is on terminating and ability state is foreground, force close");
|
||
flag = false;
|
||
}
|
||
|
||
// double check to avoid the ability has been removed
|
||
if (!GetAbilityRecordByToken(abilityRecord->GetToken())) {
|
||
HILOG_ERROR("Ability has already been removed");
|
||
return ERR_OK;
|
||
}
|
||
|
||
abilityRecord->SetTerminatingState();
|
||
// save result to caller AbilityRecord
|
||
if (resultWant != nullptr) {
|
||
abilityRecord->SaveResultToCallers(resultCode, resultWant);
|
||
}
|
||
|
||
return TerminateAbilityLocked(abilityRecord, flag);
|
||
}
|
||
|
||
int MissionListManager::TerminateAbility(const std::shared_ptr<AbilityRecord> &caller, int requestCode)
|
||
{
|
||
HILOG_DEBUG("Terminate ability with result called.");
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
std::shared_ptr<AbilityRecord> targetAbility = GetAbilityRecordByCaller(caller, requestCode);
|
||
if (!targetAbility) {
|
||
HILOG_ERROR("%{public}s, Can't find target ability", __func__);
|
||
return NO_FOUND_ABILITY_BY_CALLER;
|
||
}
|
||
|
||
int result = AbilityUtil::JudgeAbilityVisibleControl(targetAbility->GetAbilityInfo());
|
||
if (result != ERR_OK) {
|
||
HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__);
|
||
return result;
|
||
}
|
||
|
||
return TerminateAbility(targetAbility, DEFAULT_INVAL_VALUE, nullptr, true);
|
||
}
|
||
|
||
int MissionListManager::TerminateAbilityLocked(const std::shared_ptr<AbilityRecord> &abilityRecord, bool flag)
|
||
{
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("Terminate ability locked, ability is %{public}s.", element.c_str());
|
||
// remove AbilityRecord out of stack
|
||
RemoveTerminatingAbility(abilityRecord, flag);
|
||
abilityRecord->SendResultToCallers();
|
||
|
||
// 1. if the ability was foregorund, first should find wether there is other ability foregorund
|
||
if (abilityRecord->IsAbilityState(FOREGROUND) || abilityRecord->IsAbilityState(FOREGROUNDING)) {
|
||
HILOG_DEBUG("current ability is active");
|
||
if (abilityRecord->GetNextAbilityRecord()) {
|
||
abilityRecord->GetNextAbilityRecord()->ProcessForegroundAbility();
|
||
} else {
|
||
MoveToBackgroundTask(abilityRecord);
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
|
||
// 2. if the ability was BACKGROUNDING, waiting for completeBackgroundNew
|
||
|
||
// 3. ability on background, schedule to terminate.
|
||
if (abilityRecord->GetAbilityState() == AbilityState::BACKGROUND) {
|
||
auto self(shared_from_this());
|
||
auto task = [abilityRecord, self]() {
|
||
HILOG_WARN("Disconnect ability terminate timeout.");
|
||
self->CompleteTerminate(abilityRecord);
|
||
};
|
||
abilityRecord->Terminate(task);
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief This method aims to do things as below
|
||
* 1. remove the mission from the current missionList
|
||
* 2. if the current missionList is empty after, then remove from the manager
|
||
* 3. if the current ability is foreground, then should schedule the next ability to foreground before terminate
|
||
*
|
||
* @param abilityRecord the ability that was terminating
|
||
*/
|
||
void MissionListManager::RemoveTerminatingAbility(const std::shared_ptr<AbilityRecord> &abilityRecord, bool flag)
|
||
{
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("Remove terminating ability, ability is %{public}s.", element.c_str());
|
||
if (GetAbilityFromTerminateList(abilityRecord->GetToken())) {
|
||
abilityRecord->SetNextAbilityRecord(nullptr);
|
||
HILOG_DEBUG("Find ability in terminating list, return.");
|
||
return;
|
||
}
|
||
|
||
auto missionList = abilityRecord->GetOwnedMissionList();
|
||
CHECK_POINTER(missionList);
|
||
|
||
missionList->RemoveMissionByAbilityRecord(abilityRecord);
|
||
DelayedSingleton<AppScheduler>::GetInstance()->PrepareTerminate(abilityRecord->GetToken());
|
||
terminateAbilityList_.push_back(abilityRecord);
|
||
|
||
if (missionList->IsEmpty()) {
|
||
HILOG_DEBUG("Remove terminating ability, missionList is empty, remove.");
|
||
RemoveMissionList(missionList);
|
||
}
|
||
|
||
// 1. clear old
|
||
abilityRecord->SetNextAbilityRecord(nullptr);
|
||
// 2. if the ability to terminate is background, just background
|
||
if (!(abilityRecord->IsAbilityState(FOREGROUND) || abilityRecord->IsAbilityState(FOREGROUNDING))) {
|
||
HILOG_DEBUG("Ability state is %{public}d, just return.", abilityRecord->GetAbilityState());
|
||
return;
|
||
}
|
||
// 3. if close ability, noting to do
|
||
if (!flag) {
|
||
HILOG_DEBUG("Close ability schedule.");
|
||
return;
|
||
}
|
||
|
||
// 4. the ability should find the next ability to foreground
|
||
std::shared_ptr<AbilityRecord> needTopAbility;
|
||
if (missionList->IsEmpty()) {
|
||
HILOG_DEBUG("MissionList is empty, next is launcher.");
|
||
needTopAbility = GetCurrentTopAbilityLocked();
|
||
} else {
|
||
needTopAbility = missionList->GetTopAbility();
|
||
}
|
||
|
||
if (!needTopAbility) {
|
||
HILOG_DEBUG("The ability need to top is null.");
|
||
return;
|
||
}
|
||
AppExecFwk::ElementName elementName = needTopAbility->GetWant().GetElement();
|
||
HILOG_DEBUG("Next top ability is %{public}s, state is %{public}d, minimizeReason is %{public}d.",
|
||
elementName.GetURI().c_str(), needTopAbility->GetAbilityState(), needTopAbility->IsMinimizeFromUser());
|
||
|
||
// 5. if caller is recent, close
|
||
if (elementName.GetBundleName() == AbilityConfig::LAUNCHER_BUNDLE_NAME
|
||
&& elementName.GetAbilityName() == AbilityConfig::LAUNCHER_RECENT_ABILITY_NAME) {
|
||
HILOG_DEBUG("Next to need is recent, just to launcher.");
|
||
needTopAbility = launcherList_->GetLauncherRoot();
|
||
}
|
||
|
||
if (!needTopAbility) {
|
||
HILOG_DEBUG("NeedTopAbility of launcherRoot is null.");
|
||
return;
|
||
}
|
||
|
||
if (!needTopAbility->IsForeground() && !needTopAbility->IsMinimizeFromUser()) {
|
||
HILOG_DEBUG("%{public}s is need to foreground.", elementName.GetURI().c_str());
|
||
abilityRecord->SetNextAbilityRecord(needTopAbility);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::RemoveMissionList(const std::shared_ptr<MissionList> &missionList)
|
||
{
|
||
if (missionList == nullptr) {
|
||
return;
|
||
}
|
||
|
||
for (auto iter = currentMissionLists_.begin(); iter != currentMissionLists_.end(); iter++) {
|
||
if ((*iter) == missionList) {
|
||
currentMissionLists_.erase(iter);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
int MissionListManager::DispatchTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE);
|
||
if (abilityRecord->GetAbilityState() != AbilityState::TERMINATING) {
|
||
HILOG_ERROR("DispatchTerminate error, ability state is %{public}d", abilityRecord->GetAbilityState());
|
||
return INNER_ERR;
|
||
}
|
||
|
||
// remove terminate timeout task.
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler.");
|
||
handler->RemoveTask(std::to_string(abilityRecord->GetEventId()));
|
||
auto self(shared_from_this());
|
||
auto task = [self, abilityRecord]() { self->CompleteTerminate(abilityRecord); };
|
||
handler->PostTask(task);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::CompleteTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
CHECK_POINTER(abilityRecord);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (abilityRecord->GetAbilityState() != AbilityState::TERMINATING) {
|
||
HILOG_ERROR("%{public}s, ability is not terminating.", __func__);
|
||
return;
|
||
}
|
||
|
||
// notify AppMS terminate
|
||
if (abilityRecord->TerminateAbility() != ERR_OK) {
|
||
// Don't return here
|
||
HILOG_ERROR("AppMS fail to terminate ability.");
|
||
}
|
||
|
||
CompleteTerminateAndUpdateMission(abilityRecord);
|
||
}
|
||
|
||
void MissionListManager::CompleteTerminateAndUpdateMission(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
CHECK_POINTER(abilityRecord);
|
||
for (auto it : terminateAbilityList_) {
|
||
if (it == abilityRecord) {
|
||
terminateAbilityList_.remove(it);
|
||
// update inner mission info time
|
||
if (abilityRecord->IsDlp() || abilityRecord->GetAbilityInfo().removeMissionAfterTerminate) {
|
||
RemoveMissionLocked(abilityRecord->GetMissionId());
|
||
return;
|
||
}
|
||
InnerMissionInfo innerMissionInfo;
|
||
int result = DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
abilityRecord->GetMissionId(), innerMissionInfo);
|
||
if (result != 0) {
|
||
HILOG_INFO("Get missionInfo error, result is %{public}d, missionId is %{public}d",
|
||
result, abilityRecord->GetMissionId());
|
||
break;
|
||
}
|
||
innerMissionInfo.missionInfo.time = GetCurrentTime();
|
||
innerMissionInfo.missionInfo.runningState = -1;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(innerMissionInfo);
|
||
HILOG_DEBUG("Destroy ability record count %{public}ld", abilityRecord.use_count());
|
||
break;
|
||
}
|
||
HILOG_WARN("Can't find ability in terminate list.");
|
||
}
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetAbilityFromTerminateList(const sptr<IRemoteObject> &token)
|
||
{
|
||
if (!token) {
|
||
return nullptr;
|
||
}
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
for (auto abilityRecord : terminateAbilityList_) {
|
||
// token is type of IRemoteObject, abilityRecord->GetToken() is type of Token extending from IRemoteObject.
|
||
if (abilityRecord && abilityRecord->GetToken() && token == abilityRecord->GetToken()->AsObject()) {
|
||
return abilityRecord;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
int MissionListManager::ClearMission(int missionId)
|
||
{
|
||
if (missionId < 0) {
|
||
HILOG_ERROR("Mission id is invalid.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto mission = GetMissionById(missionId);
|
||
if (mission && mission->GetMissionList() && mission->GetMissionList()->GetType() == MissionListType::LAUNCHER) {
|
||
HILOG_ERROR("Mission id is launcher, can not clear.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
return ClearMissionLocked(missionId, mission);
|
||
}
|
||
|
||
int MissionListManager::ClearMissionLocked(int missionId, std::shared_ptr<Mission> mission)
|
||
{
|
||
if (missionId != -1) {
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->DeleteMissionInfo(missionId);
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionDestroyed(missionId);
|
||
}
|
||
}
|
||
if (mission == nullptr) {
|
||
HILOG_DEBUG("ability has already terminate, just remove mission.");
|
||
return ERR_OK;
|
||
}
|
||
|
||
auto abilityRecord = mission->GetAbilityRecord();
|
||
if (abilityRecord == nullptr || abilityRecord->IsTerminating()) {
|
||
HILOG_WARN("Ability record is not exist or is on terminating.");
|
||
return ERR_OK;
|
||
}
|
||
|
||
abilityRecord->SetTerminatingState();
|
||
auto ret = TerminateAbilityLocked(abilityRecord, false);
|
||
if (ret != ERR_OK) {
|
||
HILOG_ERROR("clear mission error: %{public}d.", ret);
|
||
return REMOVE_MISSION_FAILED;
|
||
}
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
int MissionListManager::ClearAllMissions()
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->DeleteAllMissionInfos(listenerController_);
|
||
std::list<std::shared_ptr<Mission>> foregroundAbilities;
|
||
ClearAllMissionsLocked(defaultStandardList_->GetAllMissions(), foregroundAbilities, false);
|
||
ClearAllMissionsLocked(defaultSingleList_->GetAllMissions(), foregroundAbilities, false);
|
||
|
||
for (auto listIter = currentMissionLists_.begin(); listIter != currentMissionLists_.end();) {
|
||
auto missionList = (*listIter);
|
||
listIter++;
|
||
if (!missionList || missionList->GetType() == MissionListType::LAUNCHER) {
|
||
continue;
|
||
}
|
||
ClearAllMissionsLocked(missionList->GetAllMissions(), foregroundAbilities, true);
|
||
}
|
||
|
||
ClearAllMissionsLocked(foregroundAbilities, foregroundAbilities, false);
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::ClearAllMissionsLocked(std::list<std::shared_ptr<Mission>> &missionList,
|
||
std::list<std::shared_ptr<Mission>> &foregroundAbilities, bool searchActive)
|
||
{
|
||
for (auto listIter = missionList.begin(); listIter != missionList.end();) {
|
||
auto mission = (*listIter);
|
||
listIter++;
|
||
if (!mission || mission->IsLockedState()) {
|
||
continue;
|
||
}
|
||
|
||
if (searchActive && mission->GetAbilityRecord() && mission->GetAbilityRecord()->IsActiveState()) {
|
||
foregroundAbilities.push_front(mission);
|
||
continue;
|
||
}
|
||
ClearMissionLocked(-1, mission);
|
||
}
|
||
}
|
||
|
||
int MissionListManager::SetMissionLockedState(int missionId, bool lockedState)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (missionId < 0) {
|
||
HILOG_ERROR("param is invalid");
|
||
return MISSION_NOT_FOUND;
|
||
}
|
||
std::shared_ptr<Mission> mission = GetMissionById(missionId);
|
||
if (mission) {
|
||
mission->SetLockedState(lockedState);
|
||
}
|
||
|
||
// update inner mission info time
|
||
InnerMissionInfo innerMissionInfo;
|
||
auto ret = DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(missionId, innerMissionInfo);
|
||
if (ret != 0) {
|
||
HILOG_ERROR("mission is not exist, missionId %{public}d", missionId);
|
||
return MISSION_NOT_FOUND;
|
||
}
|
||
innerMissionInfo.missionInfo.lockedState = lockedState;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(innerMissionInfo);
|
||
return ERR_OK;
|
||
}
|
||
|
||
void MissionListManager::MoveToBackgroundTask(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
if (abilityRecord == nullptr) {
|
||
HILOG_ERROR("Move the ability to background fail, ability record is null.");
|
||
return;
|
||
}
|
||
HILOG_INFO("Move the ability to background, ability:%{public}s.", abilityRecord->GetAbilityInfo().name.c_str());
|
||
abilityRecord->SetIsNewWant(false);
|
||
auto self(shared_from_this());
|
||
UpdateMissionSnapshot(abilityRecord);
|
||
auto task = [abilityRecord, self]() {
|
||
HILOG_ERROR("Mission list manager move to background timeout.");
|
||
self->PrintTimeOutLog(abilityRecord, AbilityManagerService::BACKGROUNDNEW_TIMEOUT_MSG);
|
||
self->CompleteBackground(abilityRecord);
|
||
};
|
||
abilityRecord->BackgroundAbility(task);
|
||
}
|
||
|
||
void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId)
|
||
{
|
||
if (ability == nullptr) {
|
||
HILOG_ERROR("ability is nullptr");
|
||
return;
|
||
}
|
||
|
||
AppExecFwk::RunningProcessInfo processInfo = {};
|
||
DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByToken(ability->GetToken(), processInfo);
|
||
std::string msgContent;
|
||
switch (msgId) {
|
||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||
msgContent = "ability load timeout";
|
||
break;
|
||
case AbilityManagerService::ACTIVE_TIMEOUT_MSG:
|
||
msgContent = "ability active timeout";
|
||
break;
|
||
case AbilityManagerService::INACTIVE_TIMEOUT_MSG:
|
||
msgContent = "ability inactive timeout";
|
||
break;
|
||
case AbilityManagerService::FOREGROUNDNEW_TIMEOUT_MSG:
|
||
msgContent = "ability foregroundnew timeout";
|
||
break;
|
||
case AbilityManagerService::BACKGROUNDNEW_TIMEOUT_MSG:
|
||
msgContent = "ability backgroundnew timeout";
|
||
break;
|
||
case AbilityManagerService::TERMINATE_TIMEOUT_MSG:
|
||
msgContent = "ability terminate timeout";
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
std::string eventType = "LIFECYCLE_TIMEOUT";
|
||
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
|
||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||
EVENT_KEY_UID, std::to_string(processInfo.uid_),
|
||
EVENT_KEY_PID, std::to_string(processInfo.pid_),
|
||
EVENT_KEY_PACKAGE_NAME, processInfo.bundleNames,
|
||
EVENT_KEY_PROCESS_NAME, processInfo.processName_,
|
||
EVENT_KEY_MESSAGE, msgContent);
|
||
|
||
HILOG_WARN("LIFECYCLE_TIMEOUT: uid:%{public}d, pid:%{public}d, abilityName: %{public}s, msg: %{public}s",
|
||
processInfo.uid_,
|
||
processInfo.pid_,
|
||
ability->GetAbilityInfo().name.c_str(),
|
||
msgContent.c_str());
|
||
}
|
||
|
||
void MissionListManager::UpdateMissionSnapshot(const std::shared_ptr<AbilityRecord>& abilityRecord)
|
||
{
|
||
CHECK_POINTER(abilityRecord);
|
||
int32_t missionId = abilityRecord->GetMissionId();
|
||
MissionSnapshot snapshot;
|
||
snapshot.isPrivate = abilityRecord->IsDlp();
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionSnapshot(missionId, abilityRecord->GetToken(),
|
||
snapshot);
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionSnapshotChanged(missionId);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::OnTimeOut(uint32_t msgId, int64_t eventId)
|
||
{
|
||
HILOG_DEBUG("On timeout, msgId is %{public}d", msgId);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityRecordByEventId(eventId);
|
||
if (abilityRecord == nullptr) {
|
||
HILOG_ERROR("MissionListManager 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());
|
||
|
||
#ifdef SUPPORT_GRAPHICS
|
||
if (abilityRecord->IsStartingWindow()) {
|
||
CancelStartingWindow(abilityRecord->GetToken(), false);
|
||
}
|
||
#endif
|
||
|
||
PrintTimeOutLog(abilityRecord, msgId);
|
||
switch (msgId) {
|
||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||
HandleLoadTimeout(abilityRecord);
|
||
break;
|
||
case AbilityManagerService::ACTIVE_TIMEOUT_MSG:
|
||
break;
|
||
case AbilityManagerService::INACTIVE_TIMEOUT_MSG:
|
||
case AbilityManagerService::FOREGROUNDNEW_TIMEOUT_MSG:
|
||
HandleForgroundNewTimeout(abilityRecord);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void MissionListManager::HandleLoadTimeout(const std::shared_ptr<AbilityRecord> &ability)
|
||
{
|
||
if (ability == nullptr) {
|
||
HILOG_ERROR("MissionListManager on time out event: ability record is nullptr.");
|
||
return;
|
||
}
|
||
// root launcher load timeout, notify appMs force terminate the ability and restart immediately.
|
||
if (ability->IsLauncherAbility() && ability->IsLauncherRoot()) {
|
||
ability->SetRestarting(true);
|
||
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(ability->GetToken());
|
||
HILOG_INFO("Launcher root load timeout, restart.");
|
||
DelayedStartLauncher();
|
||
return;
|
||
}
|
||
|
||
// other
|
||
HandleTimeoutAndResumeAbility(ability);
|
||
}
|
||
|
||
void MissionListManager::HandleForgroundNewTimeout(const std::shared_ptr<AbilityRecord> &ability)
|
||
{
|
||
if (ability == nullptr) {
|
||
HILOG_ERROR("MissionListManager on time out event: ability record is nullptr.");
|
||
return;
|
||
}
|
||
|
||
if (ability->GetMission()) {
|
||
ability->GetMission()->SetMovingState(false);
|
||
}
|
||
|
||
if (!ability->IsAbilityState(AbilityState::FOREGROUNDING)) {
|
||
HILOG_ERROR("this ability is not forgrounding state.");
|
||
return;
|
||
}
|
||
|
||
// root launcher load timeout, notify appMs force terminate the ability and restart immediately.
|
||
if (ability->IsLauncherAbility() && ability->IsLauncherRoot()) {
|
||
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(ability->GetToken());
|
||
HILOG_INFO("Launcher root load timeout, restart.");
|
||
DelayedStartLauncher();
|
||
return;
|
||
}
|
||
|
||
// other
|
||
HandleTimeoutAndResumeAbility(ability);
|
||
}
|
||
|
||
void MissionListManager::HandleTimeoutAndResumeAbility(const std::shared_ptr<AbilityRecord> &timeOutAbilityRecord)
|
||
{
|
||
HILOG_DEBUG("HandleTimeoutAndResumeTopAbility start");
|
||
if (timeOutAbilityRecord == nullptr) {
|
||
HILOG_ERROR("LoadAndForeGroundCommon: timeOutAbilityRecord is nullptr.");
|
||
return;
|
||
}
|
||
|
||
// complete mission list mvoing
|
||
MoveToTerminateList(timeOutAbilityRecord);
|
||
|
||
// load and foreground timeout, notify appMs force terminate the ability.
|
||
DelayedSingleton<AppScheduler>::GetInstance()->AttachTimeOut(timeOutAbilityRecord->GetToken());
|
||
|
||
// caller not exist or caller is service or timeout ability is launcher, back to launcher
|
||
auto callerAbility = timeOutAbilityRecord->GetCallerRecord();
|
||
if ((callerAbility == nullptr) ||
|
||
(callerAbility->GetAbilityInfo().type == AppExecFwk::AbilityType::SERVICE) ||
|
||
(callerAbility->GetAbilityInfo().type == AppExecFwk::AbilityType::EXTENSION) ||
|
||
timeOutAbilityRecord->IsLauncherAbility() ||
|
||
callerAbility->IsLauncherAbility()) {
|
||
HILOG_DEBUG("ability timeout, back to launcher.");
|
||
DelayedStartLauncher();
|
||
return;
|
||
}
|
||
|
||
DelayedResumeTimeout(callerAbility);
|
||
|
||
HILOG_INFO("HandleTimeoutAndResumeTopAbility end");
|
||
}
|
||
|
||
void MissionListManager::DelayedResumeTimeout(const std::shared_ptr<AbilityRecord> &callerAbility)
|
||
{
|
||
auto abilityManagerService = DelayedSingleton<AbilityManagerService>::GetInstance();
|
||
CHECK_POINTER(abilityManagerService);
|
||
auto handler = abilityManagerService->GetEventHandler();
|
||
CHECK_POINTER(handler);
|
||
std::weak_ptr<MissionListManager> wpListMgr = shared_from_this();
|
||
auto timeoutTask = [wpListMgr, callerAbility]() {
|
||
HILOG_DEBUG("The caller ability need to resume.");
|
||
auto listMgr = wpListMgr.lock();
|
||
if (listMgr) {
|
||
listMgr->BackToCaller(callerAbility);
|
||
}
|
||
};
|
||
handler->PostTask(timeoutTask, "Caller_Restart");
|
||
}
|
||
|
||
void MissionListManager::BackToCaller(const std::shared_ptr<AbilityRecord> &callerAbility)
|
||
{
|
||
HILOG_INFO("Back to Caller.");
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
// caller is already the top ability and foregroundnew.
|
||
auto topAbility = GetCurrentTopAbilityLocked();
|
||
if (callerAbility == topAbility && topAbility->IsAbilityState(AbilityState::FOREGROUND)) {
|
||
HILOG_DEBUG("caller is already the top ability and foregroundnew.");
|
||
return;
|
||
}
|
||
|
||
// other , resume caller ability to top and foreground.
|
||
MoveMissionToFront(callerAbility->GetMissionId(), false);
|
||
}
|
||
|
||
void MissionListManager::MoveToTerminateList(const std::shared_ptr<AbilityRecord>& abilityRecord)
|
||
{
|
||
HILOG_INFO("MoveToDefaultList start.");
|
||
if (abilityRecord == nullptr) {
|
||
HILOG_ERROR("timeout ability record is nullptr.");
|
||
return;
|
||
}
|
||
auto missionList = abilityRecord->GetOwnedMissionList();
|
||
if (missionList == nullptr) {
|
||
HILOG_ERROR("timeout missionList is nullptr.");
|
||
return;
|
||
}
|
||
auto selMisson = abilityRecord->GetMission();
|
||
if (selMisson == nullptr) {
|
||
HILOG_ERROR("timeout misson is nullptr.");
|
||
return;
|
||
}
|
||
|
||
missionList->RemoveMission(selMisson);
|
||
if (missionList->GetType() == MissionListType::CURRENT && missionList->IsEmpty()) {
|
||
RemoveMissionList(missionList);
|
||
}
|
||
|
||
// load timeout will not wait for died event, directly remove.
|
||
if (abilityRecord->IsAbilityState(AbilityState::INITIAL)) {
|
||
HILOG_WARN("load timeout will not wait for died event, directly remove.");
|
||
// update running state.
|
||
InnerMissionInfo info;
|
||
if (DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
selMisson->GetMissionId(), info) == 0) {
|
||
info.missionInfo.runningState = -1;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(info);
|
||
}
|
||
return;
|
||
}
|
||
HILOG_DEBUG("success move timeout ability to terminate mission list.");
|
||
// other remove to terminate list.
|
||
abilityRecord->SetTerminatingState();
|
||
terminateAbilityList_.push_back(abilityRecord);
|
||
|
||
HILOG_INFO("MoveToDefaultList end");
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetAbilityRecordByCaller(
|
||
const std::shared_ptr<AbilityRecord> &caller, int requestCode)
|
||
{
|
||
if (!caller) {
|
||
return nullptr;
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> abilityRecord = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (abilityRecord = missionList->GetAbilityRecordByCaller(caller, requestCode)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
}
|
||
|
||
if ((abilityRecord = defaultSingleList_->GetAbilityRecordByCaller(caller, requestCode)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
|
||
return defaultStandardList_->GetAbilityRecordByCaller(caller, requestCode);
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetAbilityRecordByEventId(int64_t eventId) const
|
||
{
|
||
std::shared_ptr<AbilityRecord> abilityRecord = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (abilityRecord = missionList->GetAbilityRecordById(eventId)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
}
|
||
|
||
if ((abilityRecord = defaultSingleList_->GetAbilityRecordById(eventId)) != nullptr) {
|
||
return abilityRecord;
|
||
}
|
||
|
||
return defaultStandardList_->GetAbilityRecordById(eventId);
|
||
}
|
||
|
||
void MissionListManager::OnAbilityDied(std::shared_ptr<AbilityRecord> abilityRecord, int32_t currentUserId)
|
||
{
|
||
HILOG_INFO("On ability died.");
|
||
if (!abilityRecord) {
|
||
HILOG_ERROR("OnAbilityDied come, abilityRecord is nullptr.");
|
||
return;
|
||
}
|
||
std::string element = abilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("OnAbilityDied come, ability is %{public}s", element.c_str());
|
||
if (abilityRecord->GetAbilityInfo().type != AbilityType::PAGE) {
|
||
HILOG_ERROR("Ability type is not page.");
|
||
return;
|
||
}
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
#ifdef SUPPORT_GRAPHICS
|
||
if (abilityRecord->IsStartingWindow()) {
|
||
CancelStartingWindow(abilityRecord->GetToken(), false);
|
||
}
|
||
#endif
|
||
|
||
if (abilityRecord->IsLauncherRoot() && currentUserId != userId_) {
|
||
HILOG_INFO("launcher root Ability died, state: INITIAL, %{public}d", __LINE__);
|
||
abilityRecord->SetAbilityState(AbilityState::INITIAL);
|
||
abilityRecord->SetRestarting(true);
|
||
return;
|
||
}
|
||
|
||
HandleAbilityDied(abilityRecord);
|
||
}
|
||
|
||
std::shared_ptr<MissionList> MissionListManager::GetTargetMissionList(int missionId, std::shared_ptr<Mission> &mission,
|
||
bool &isCold)
|
||
{
|
||
mission = GetMissionById(missionId);
|
||
if (mission) {
|
||
HILOG_DEBUG("get mission by id successfully, missionId: %{public}d", missionId);
|
||
auto missionList = mission->GetMissionList();
|
||
if (!missionList) {
|
||
// mission is not null ptr, so its missionList ptr should be not null ptr too.
|
||
HILOG_ERROR("mission list ptr is null ptr");
|
||
return nullptr;
|
||
}
|
||
|
||
auto missionType = missionList->GetType();
|
||
std::shared_ptr<MissionList> targetMissionList = nullptr;
|
||
switch (missionType) {
|
||
case LAUNCHER:
|
||
// not support move launcher to front.
|
||
HILOG_ERROR("get launcher mission list, missionId: %{public}d", missionId);
|
||
break;
|
||
case CURRENT:
|
||
targetMissionList = mission->GetMissionList();
|
||
break;
|
||
case DEFAULT_STANDARD:
|
||
case DEFAULT_SINGLE:
|
||
// generate a new missionList
|
||
targetMissionList = std::make_shared<MissionList>();
|
||
break;
|
||
default:
|
||
HILOG_ERROR("invalid missionType: %{public}d", missionType);
|
||
}
|
||
return targetMissionList;
|
||
}
|
||
|
||
// cannot find mission, may reasons: system restart or mission removed by system.
|
||
HILOG_INFO("cannot find mission from MissionList by missionId: %{public}d", missionId);
|
||
|
||
InnerMissionInfo innerMissionInfo;
|
||
int getMission = DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
missionId, innerMissionInfo);
|
||
if (getMission != ERR_OK) {
|
||
HILOG_ERROR("cannot find mission info from MissionInfoList by missionId: %{public}d", missionId);
|
||
return nullptr;
|
||
}
|
||
|
||
// generate a new mission and missionList
|
||
AbilityRequest abilityRequest;
|
||
int generateAbility = DelayedSingleton<AbilityManagerService>::GetInstance()->GenerateAbilityRequest(
|
||
innerMissionInfo.missionInfo.want, DEFAULT_INVAL_VALUE, abilityRequest, nullptr, userId_);
|
||
if (generateAbility != ERR_OK) {
|
||
HILOG_ERROR("cannot find generate ability request, missionId: %{public}d", missionId);
|
||
return nullptr;
|
||
}
|
||
|
||
auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest);
|
||
isCold = true;
|
||
mission = std::make_shared<Mission>(innerMissionInfo.missionInfo.id, abilityRecord, innerMissionInfo.missionName);
|
||
abilityRecord->SetMission(mission);
|
||
std::shared_ptr<MissionList> newMissionList = std::make_shared<MissionList>();
|
||
listenerController_->NotifyMissionCreated(innerMissionInfo.missionInfo.id);
|
||
return newMissionList;
|
||
}
|
||
|
||
int32_t MissionListManager::GetMissionIdByAbilityToken(const sptr<IRemoteObject> &token)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityRecordByToken(token);
|
||
if (!abilityRecord) {
|
||
return -1;
|
||
}
|
||
auto mission = abilityRecord->GetMission();
|
||
if (!mission) {
|
||
return -1;
|
||
}
|
||
return mission->GetMissionId();
|
||
}
|
||
|
||
sptr<IRemoteObject> MissionListManager::GetAbilityTokenByMissionId(int32_t missionId)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
sptr<IRemoteObject> result = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (result = missionList->GetAbilityTokenByMissionId(missionId)) != nullptr) {
|
||
return result;
|
||
}
|
||
}
|
||
|
||
if ((result = defaultSingleList_->GetAbilityTokenByMissionId(missionId)) != nullptr) {
|
||
return result;
|
||
}
|
||
|
||
return defaultStandardList_->GetAbilityTokenByMissionId((missionId));
|
||
}
|
||
|
||
void MissionListManager::UpdateMissionTimeStamp(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||
{
|
||
auto mission = abilityRecord->GetMission();
|
||
if (!mission) {
|
||
return;
|
||
}
|
||
std::string curTime = GetCurrentTime();
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionTimeStamp(mission->GetMissionId(), curTime);
|
||
}
|
||
|
||
void MissionListManager::PostStartWaittingAbility()
|
||
{
|
||
auto self(shared_from_this());
|
||
auto startWaittingAbilityTask = [self]() { self->StartWaittingAbility(); };
|
||
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
CHECK_POINTER_LOG(handler, "Fail to get AbilityEventHandler.");
|
||
|
||
/* PostTask to trigger start Ability from waiting queue */
|
||
handler->PostTask(startWaittingAbilityTask, "startWaittingAbility");
|
||
}
|
||
|
||
void MissionListManager::HandleAbilityDied(std::shared_ptr<AbilityRecord> abilityRecord)
|
||
{
|
||
HILOG_INFO("Handle Ability Died.");
|
||
CHECK_POINTER(abilityRecord);
|
||
|
||
if (abilityRecord->GetAbilityInfo().type != AbilityType::PAGE) {
|
||
HILOG_ERROR("Ability type is not page.");
|
||
return;
|
||
}
|
||
|
||
if (abilityRecord->IsLauncherAbility()) {
|
||
HandleLauncherDied(abilityRecord);
|
||
return;
|
||
}
|
||
|
||
HandleAbilityDiedByDefault(abilityRecord);
|
||
}
|
||
|
||
void MissionListManager::HandleLauncherDied(std::shared_ptr<AbilityRecord> ability)
|
||
{
|
||
HILOG_INFO("Handle launcher Ability Died.");
|
||
auto mission = ability->GetMission();
|
||
CHECK_POINTER_LOG(mission, "Fail to get launcher mission.");
|
||
auto missionList = mission->GetMissionList();
|
||
if (launcherList_ != missionList) {
|
||
HILOG_ERROR("not launcher missionList.");
|
||
return;
|
||
}
|
||
|
||
bool isForeground = ability->IsAbilityState(FOREGROUND) || ability->IsAbilityState(FOREGROUNDING);
|
||
if (ability->IsLauncherRoot()) {
|
||
HILOG_INFO("launcher root Ability died, state: INITIAL, %{public}d", __LINE__);
|
||
ability->SetAbilityState(AbilityState::INITIAL);
|
||
ability->SetRestarting(true);
|
||
} else {
|
||
HILOG_INFO("launcher Ability died, remove, %{public}d", __LINE__);
|
||
missionList->RemoveMission(mission);
|
||
}
|
||
if (isForeground) {
|
||
HILOG_INFO("active launchrer ability died, start launcher, %{public}d", __LINE__);
|
||
DelayedStartLauncher();
|
||
}
|
||
}
|
||
|
||
void MissionListManager::HandleAbilityDiedByDefault(std::shared_ptr<AbilityRecord> ability)
|
||
{
|
||
HILOG_INFO("Handle Ability DiedByDefault.");
|
||
CHECK_POINTER_LOG(ability, "ability is null.");
|
||
if (ability->IsTerminating()) {
|
||
HILOG_INFO("Handle Ability DiedByTerminating.");
|
||
CompleteTerminateAndUpdateMission(ability);
|
||
return;
|
||
}
|
||
|
||
auto mission = ability->GetMission();
|
||
CHECK_POINTER_LOG(mission, "Fail to get mission.");
|
||
auto missionList = mission->GetMissionList();
|
||
CHECK_POINTER_LOG(missionList, "Fail to get mission list.");
|
||
|
||
std::shared_ptr<AbilityRecord> launcherRoot = launcherList_->GetLauncherRoot();
|
||
bool isLauncherActive = (launcherRoot &&
|
||
(launcherRoot->IsAbilityState(FOREGROUND) || launcherRoot->IsAbilityState(FOREGROUNDING)));
|
||
bool isForeground = ability->IsAbilityState(FOREGROUND) || ability->IsAbilityState(FOREGROUNDING);
|
||
|
||
// remove from mission list.
|
||
missionList->RemoveMission(mission);
|
||
if (missionList->GetType() == MissionListType::CURRENT && missionList->IsEmpty()) {
|
||
RemoveMissionList(missionList);
|
||
}
|
||
|
||
// update running state.
|
||
if (!ability->IsUninstallAbility()) {
|
||
if (ability->IsDlp() || ability->GetAbilityInfo().removeMissionAfterTerminate) {
|
||
RemoveMissionLocked(mission->GetMissionId());
|
||
} else {
|
||
InnerMissionInfo info;
|
||
if (DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
mission->GetMissionId(), info) == 0) {
|
||
info.missionInfo.runningState = -1;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionInfo(info);
|
||
}
|
||
}
|
||
}
|
||
|
||
// start launcher
|
||
if (isForeground && !isLauncherActive) {
|
||
HILOG_INFO("active ability died, start launcher later, %{public}d", __LINE__);
|
||
DelayedStartLauncher();
|
||
}
|
||
}
|
||
|
||
void MissionListManager::DelayedStartLauncher()
|
||
{
|
||
auto abilityManagerService = DelayedSingleton<AbilityManagerService>::GetInstance();
|
||
CHECK_POINTER(abilityManagerService);
|
||
auto handler = abilityManagerService->GetEventHandler();
|
||
CHECK_POINTER(handler);
|
||
std::weak_ptr<MissionListManager> wpListMgr = shared_from_this();
|
||
auto timeoutTask = [wpListMgr]() {
|
||
HILOG_DEBUG("The launcher needs to be restarted.");
|
||
auto listMgr = wpListMgr.lock();
|
||
if (listMgr) {
|
||
listMgr->BackToLauncher();
|
||
}
|
||
};
|
||
handler->PostTask(timeoutTask, "Launcher_Restart");
|
||
}
|
||
|
||
void MissionListManager::BackToLauncher()
|
||
{
|
||
HILOG_INFO("Back to launcher.");
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
CHECK_POINTER(launcherList_);
|
||
|
||
auto launcherRootAbility = launcherList_->GetLauncherRoot();
|
||
if (!launcherRootAbility) {
|
||
HILOG_WARN("no root launcher ability, no need back to launcher.");
|
||
return;
|
||
}
|
||
|
||
if (launcherRootAbility->GetAbilityInfo().bundleName != AbilityConfig::LAUNCHER_BUNDLE_NAME) {
|
||
HILOG_WARN("not launcher mission, no need back to launcher.");
|
||
return;
|
||
}
|
||
|
||
auto launcherRootMission = launcherRootAbility->GetMission();
|
||
if (!launcherRootMission) {
|
||
HILOG_WARN("no root launcher mission, no need back to launcher.");
|
||
return;
|
||
}
|
||
|
||
std::queue<AbilityRequest> emptyQueue;
|
||
std::swap(waittingAbilityQueue_, emptyQueue);
|
||
|
||
launcherList_->AddMissionToTop(launcherRootMission);
|
||
MoveMissionListToTop(launcherList_);
|
||
launcherRootAbility->ProcessForegroundAbility();
|
||
}
|
||
|
||
#ifdef SUPPORT_GRAPHICS
|
||
int MissionListManager::SetMissionLabel(const sptr<IRemoteObject> &token, const std::string &label)
|
||
{
|
||
if (!token) {
|
||
HILOG_INFO("SetMissionLabel token is nullptr.");
|
||
return -1;
|
||
}
|
||
|
||
auto missionId = GetMissionIdByAbilityToken(token);
|
||
if (missionId <= 0) {
|
||
HILOG_INFO("SetMissionLabel find mission failed.");
|
||
return -1;
|
||
}
|
||
|
||
return DelayedSingleton<MissionInfoMgr>::GetInstance()->UpdateMissionLabel(missionId, label);
|
||
}
|
||
|
||
int MissionListManager::SetMissionIcon(const sptr<IRemoteObject> &token, const std::shared_ptr<Media::PixelMap> &icon)
|
||
{
|
||
if (!token) {
|
||
HILOG_INFO("SetMissionIcon token is nullptr.");
|
||
return -1;
|
||
}
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto missionId = GetMissionIdByAbilityToken(token);
|
||
if (missionId <= 0) {
|
||
HILOG_INFO("SetMissionIcon find mission failed.");
|
||
return -1;
|
||
}
|
||
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionIconChanged(missionId, icon);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void MissionListManager::SetShowWhenLocked(const AppExecFwk::AbilityInfo &abilityInfo,
|
||
sptr<AbilityTransitionInfo> &info) const
|
||
{
|
||
bool showOnLockScreen = false;
|
||
std::vector<AppExecFwk::CustomizeData> datas = abilityInfo.metaData.customizeData;
|
||
for (AppExecFwk::CustomizeData data : datas) {
|
||
if (data.name == SHOW_ON_LOCK_SCREEN) {
|
||
showOnLockScreen = true;
|
||
}
|
||
}
|
||
if (showOnLockScreen) {
|
||
info->isShowWhenLocked_ = true;
|
||
}
|
||
}
|
||
|
||
sptr<IWindowManagerServiceHandler> MissionListManager::GetWMSHandler() const
|
||
{
|
||
auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
|
||
if (!abilityMgr) {
|
||
HILOG_WARN("%{public}s, Get Ability Manager Service failed.", __func__);
|
||
return nullptr;
|
||
}
|
||
return abilityMgr->GetWMSHandler();
|
||
}
|
||
|
||
void MissionListManager::SetAbilityTransitionInfo(const AppExecFwk::AbilityInfo &abilityInfo,
|
||
sptr<AbilityTransitionInfo> &info) const
|
||
{
|
||
info->abilityName_ = abilityInfo.name;
|
||
info->bundleName_ = abilityInfo.bundleName;
|
||
SetShowWhenLocked(abilityInfo, info);
|
||
}
|
||
|
||
void MissionListManager::SetWindowModeAndDisplayId(sptr<AbilityTransitionInfo> &info, const Want &want) const
|
||
{
|
||
auto mode = want.GetIntParam(Want::PARAM_RESV_WINDOW_MODE, -1);
|
||
auto displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, -1);
|
||
if (mode != -1) {
|
||
info->mode_ = static_cast<uint32_t>(mode);
|
||
}
|
||
if (displayId != -1) {
|
||
info->displayId_ = static_cast<uint64_t>(displayId);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::NotifyAnimationFromRecentTask(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
||
const std::shared_ptr<StartOptions> &startOptions, const Want &want) const
|
||
{
|
||
auto abilityInfo = abilityRecord->GetAbilityInfo();
|
||
if (abilityInfo.name == AbilityConfig::GRANT_ABILITY_ABILITY_NAME &&
|
||
abilityInfo.bundleName == AbilityConfig::GRANT_ABILITY_BUNDLE_NAME) {
|
||
HILOG_INFO("%{public}s, ignore GrantAbility.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto windowHandler = GetWMSHandler();
|
||
if (!windowHandler) {
|
||
HILOG_WARN("%{public}s, Get WMS handler failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto toInfo = CreateAbilityTransitionInfo(abilityRecord->GetToken(), startOptions, want);
|
||
SetAbilityTransitionInfo(abilityInfo, toInfo);
|
||
sptr<AbilityTransitionInfo> fromInfo = new AbilityTransitionInfo();
|
||
fromInfo->isRecent_ = true;
|
||
windowHandler->NotifyWindowTransition(fromInfo, toInfo);
|
||
}
|
||
|
||
void MissionListManager::NotifyAnimationFromStartingAbility(const std::shared_ptr<AbilityRecord> &callerAbility,
|
||
const AbilityRequest &abilityRequest, const sptr<IRemoteObject> abilityToken) const
|
||
{
|
||
auto abilityInfo = abilityRequest.abilityInfo;
|
||
if (abilityInfo.name == AbilityConfig::GRANT_ABILITY_ABILITY_NAME &&
|
||
abilityInfo.bundleName == AbilityConfig::GRANT_ABILITY_BUNDLE_NAME) {
|
||
HILOG_INFO("%{public}s, ignore GrantAbility.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto windowHandler = GetWMSHandler();
|
||
if (!windowHandler) {
|
||
HILOG_WARN("%{public}s, Get WMS handler failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
sptr<AbilityTransitionInfo> fromInfo = new AbilityTransitionInfo();
|
||
if (callerAbility) {
|
||
auto callerAbilityInfo = callerAbility->GetAbilityInfo();
|
||
SetAbilityTransitionInfo(callerAbilityInfo, fromInfo);
|
||
fromInfo->abilityToken_ = callerAbility->GetToken();
|
||
} else {
|
||
fromInfo->abilityToken_ = abilityRequest.callerToken;
|
||
}
|
||
|
||
auto toInfo = CreateAbilityTransitionInfo(abilityRequest, abilityToken);
|
||
SetAbilityTransitionInfo(abilityInfo, toInfo);
|
||
|
||
windowHandler->NotifyWindowTransition(fromInfo, toInfo);
|
||
}
|
||
|
||
std::shared_ptr<Global::Resource::ResourceManager> MissionListManager::CreateResourceManager(
|
||
const AppExecFwk::AbilityInfo &abilityInfo) const
|
||
{
|
||
std::shared_ptr<Global::Resource::ResourceManager> resourceMgr(Global::Resource::CreateResourceManager());
|
||
if (!resourceMgr->AddResource(abilityInfo.resourcePath.c_str())) {
|
||
HILOG_WARN("%{public}s AddResource failed.", __func__);
|
||
}
|
||
|
||
std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
|
||
resConfig->SetLocaleInfo("zh", "Hans", "CN");
|
||
resourceMgr->UpdateResConfig(*resConfig);
|
||
return resourceMgr;
|
||
}
|
||
|
||
sptr<Media::PixelMap> MissionListManager::GetPixelMap(const uint32_t windowIconId,
|
||
std::shared_ptr<Global::Resource::ResourceManager> resourceMgr) const
|
||
{
|
||
std::string iconPath;
|
||
auto iconPathErrval = resourceMgr->GetMediaById(windowIconId, iconPath);
|
||
if (iconPathErrval != OHOS::Global::Resource::RState::SUCCESS) {
|
||
HILOG_ERROR("GetMediaById iconPath failed");
|
||
return nullptr;
|
||
}
|
||
HILOG_DEBUG("GetMediaById iconPath: %{private}s", iconPath.c_str());
|
||
|
||
uint32_t errorCode = 0;
|
||
Media::SourceOptions opts;
|
||
auto imageSource = Media::ImageSource::CreateImageSource(iconPath, opts, errorCode);
|
||
if (errorCode != 0) {
|
||
HILOG_ERROR("Failed to create image source path %{private}s err %{public}d", iconPath.c_str(), errorCode);
|
||
return nullptr;
|
||
}
|
||
|
||
Media::DecodeOptions decodeOpts;
|
||
auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
|
||
if (errorCode != 0) {
|
||
HILOG_ERROR("Failed to create pixelmap path %{private}s err %{public}d", iconPath.c_str(), errorCode);
|
||
return nullptr;
|
||
}
|
||
HILOG_DEBUG("%{public}s OUT.", __func__);
|
||
return sptr<Media::PixelMap>(pixelMapPtr.release());
|
||
}
|
||
|
||
sptr<AbilityTransitionInfo> MissionListManager::CreateAbilityTransitionInfo(const sptr<IRemoteObject> abilityToken,
|
||
const std::shared_ptr<StartOptions> &startOptions, const Want &want) const
|
||
{
|
||
sptr<AbilityTransitionInfo> info = new AbilityTransitionInfo();
|
||
if (startOptions != nullptr) {
|
||
info->mode_ = static_cast<uint32_t>(startOptions->GetWindowMode());
|
||
info->displayId_ = static_cast<uint64_t>(startOptions->GetDisplayID());
|
||
} else {
|
||
SetWindowModeAndDisplayId(info, want);
|
||
}
|
||
info->abilityToken_ = abilityToken;
|
||
return info;
|
||
}
|
||
|
||
sptr<AbilityTransitionInfo> MissionListManager::CreateAbilityTransitionInfo(const AbilityRequest &abilityRequest,
|
||
const sptr<IRemoteObject> abilityToken) const
|
||
{
|
||
sptr<AbilityTransitionInfo> info = new AbilityTransitionInfo();
|
||
auto abilityStartSetting = abilityRequest.startSetting;
|
||
if (abilityStartSetting) {
|
||
auto mode = std::stoi(abilityStartSetting->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY));
|
||
info->mode_ = static_cast<uint32_t>(mode);
|
||
auto displayId = std::stoi(abilityStartSetting->GetProperty(AbilityStartSetting::WINDOW_DISPLAY_ID_KEY));
|
||
info->displayId_ = static_cast<uint64_t>(displayId);
|
||
} else {
|
||
SetWindowModeAndDisplayId(info, abilityRequest.want);
|
||
}
|
||
info->abilityToken_ = abilityToken;
|
||
return info;
|
||
}
|
||
|
||
void MissionListManager::NotifyStartingWindow(bool isCold, const std::shared_ptr<AbilityRecord> &targetAbilityRecord,
|
||
std::shared_ptr<StartOptions> &startOptions, int32_t missionId)
|
||
{
|
||
InnerMissionInfo innerMissionInfo;
|
||
int getMission = DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(
|
||
missionId, innerMissionInfo);
|
||
if (getMission != ERR_OK) {
|
||
HILOG_ERROR("cannot find mission info from MissionInfoList by missionId: %{public}d", missionId);
|
||
return;
|
||
}
|
||
|
||
auto want = innerMissionInfo.missionInfo.want;
|
||
auto self(weak_from_this());
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
if (handler == nullptr) {
|
||
return;
|
||
}
|
||
|
||
targetAbilityRecord->SetStartingWindow(true);
|
||
if (isCold) {
|
||
auto task = [self, targetAbilityRecord, startOptions, want] {
|
||
auto mgr = self.lock();
|
||
if (mgr) {
|
||
AbilityRequest abilityRequest;
|
||
mgr->StartingWindowCold(targetAbilityRecord, startOptions, want, abilityRequest);
|
||
mgr->NotifyAnimationFromRecentTask(targetAbilityRecord, startOptions, want);
|
||
}
|
||
};
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
} else {
|
||
auto task = [self, targetAbilityRecord, startOptions, want, missionId] {
|
||
auto mgr = self.lock();
|
||
if (mgr) {
|
||
AbilityRequest abilityRequest;
|
||
mgr->StartingWindowHot(targetAbilityRecord, startOptions, want, abilityRequest, missionId);
|
||
mgr->NotifyAnimationFromRecentTask(targetAbilityRecord, startOptions, want);
|
||
}
|
||
};
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::NotifyStartingWindow(bool isCold, const std::shared_ptr<Mission> &targetMission,
|
||
const std::shared_ptr<AbilityRecord> &targetAbilityRecord, const AbilityRequest &abilityRequest,
|
||
const std::shared_ptr<AbilityRecord> &callerAbility)
|
||
{
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
if (handler == nullptr) {
|
||
HILOG_ERROR("Fail to get AbilityEventHandler.");
|
||
return;
|
||
}
|
||
|
||
auto self(weak_from_this());
|
||
targetAbilityRecord->SetStartingWindow(true);
|
||
if (isCold) {
|
||
auto task = [self, targetAbilityRecord, abilityRequest] {
|
||
auto mgr = self.lock();
|
||
if (mgr) {
|
||
std::shared_ptr<StartOptions> startOptions = nullptr;
|
||
Want want;
|
||
mgr->StartingWindowCold(targetAbilityRecord, startOptions, want, abilityRequest);
|
||
}
|
||
};
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
} else {
|
||
auto missionId = targetMission->GetMissionId();
|
||
auto task = [self, targetAbilityRecord, abilityRequest, missionId] {
|
||
auto mgr = self.lock();
|
||
if (mgr) {
|
||
std::shared_ptr<StartOptions> startOptions = nullptr;
|
||
Want want;
|
||
mgr->StartingWindowHot(targetAbilityRecord, startOptions, want, abilityRequest, missionId);
|
||
}
|
||
};
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
}
|
||
|
||
auto state = targetAbilityRecord->GetAbilityState();
|
||
if (state != AbilityState::FOREGROUND && state != AbilityState::FOREGROUNDING) {
|
||
auto abilityToken = targetAbilityRecord->GetToken();
|
||
auto task = [self, callerAbility, abilityRequest, abilityToken] {
|
||
auto mgr = self.lock();
|
||
if (mgr) {
|
||
mgr->NotifyAnimationFromStartingAbility(callerAbility, abilityRequest, abilityToken);
|
||
}
|
||
};
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::StartingWindowCold(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
||
const std::shared_ptr<StartOptions> &startOptions, const Want &want, const AbilityRequest &abilityRequest) const
|
||
{
|
||
auto abilityInfo = abilityRecord->GetAbilityInfo();
|
||
if (abilityInfo.name == AbilityConfig::GRANT_ABILITY_ABILITY_NAME &&
|
||
abilityInfo.bundleName == AbilityConfig::GRANT_ABILITY_BUNDLE_NAME) {
|
||
HILOG_INFO("%{public}s, ignore GrantAbility.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto windowHandler = GetWMSHandler();
|
||
if (!windowHandler) {
|
||
HILOG_WARN("%{public}s, Get WMS handler failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto resourceMgr = CreateResourceManager(abilityInfo);
|
||
if (!resourceMgr) {
|
||
HILOG_WARN("%{public}s, Get resourceMgr failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto windowIconId = static_cast<uint32_t>(abilityInfo.startWindowIconId);
|
||
auto pixelMap = GetPixelMap(windowIconId, resourceMgr);
|
||
|
||
uint32_t bgColor = 0;
|
||
auto colorId = static_cast<uint32_t>(abilityInfo.startWindowBackgroundId);
|
||
auto colorErrval = resourceMgr->GetColorById(colorId, bgColor);
|
||
if (colorErrval != OHOS::Global::Resource::RState::SUCCESS) {
|
||
HILOG_WARN("%{public}s. Failed to GetColorById.", __func__);
|
||
bgColor = 0xffffffff;
|
||
}
|
||
HILOG_DEBUG("%{public}s colorId is %{public}u, bgColor is %{public}u.", __func__, colorId, bgColor);
|
||
|
||
auto abilityToken = abilityRecord->GetToken();
|
||
if (!abilityToken) {
|
||
HILOG_WARN("%{public}s. ability token is nullptr.", __func__);
|
||
return;
|
||
}
|
||
sptr<AbilityTransitionInfo> info;
|
||
if (startOptions) {
|
||
info = CreateAbilityTransitionInfo(abilityToken, startOptions, want);
|
||
} else {
|
||
info = CreateAbilityTransitionInfo(abilityRequest, abilityToken);
|
||
}
|
||
|
||
windowHandler->StartingWindow(info, pixelMap, bgColor);
|
||
CancelStartingWindow(abilityToken, true);
|
||
}
|
||
|
||
void MissionListManager::StartingWindowHot(const std::shared_ptr<AbilityRecord> &abilityRecord,
|
||
const std::shared_ptr<StartOptions> &startOptions, const Want &want, const AbilityRequest &abilityRequest,
|
||
int32_t missionId) const
|
||
{
|
||
auto abilityInfo = abilityRecord->GetAbilityInfo();
|
||
if (abilityInfo.name == AbilityConfig::GRANT_ABILITY_ABILITY_NAME &&
|
||
abilityInfo.bundleName == AbilityConfig::GRANT_ABILITY_BUNDLE_NAME) {
|
||
HILOG_INFO("%{public}s, ignore GrantAbility.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto windowHandler = GetWMSHandler();
|
||
if (!windowHandler) {
|
||
HILOG_WARN("%{public}s, Get WMS handler failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto abilityToken = abilityRecord->GetToken();
|
||
if (!abilityToken) {
|
||
HILOG_WARN("%{public}s. ability token is nullptr.", __func__);
|
||
return;
|
||
}
|
||
sptr<AbilityTransitionInfo> info;
|
||
if (startOptions) {
|
||
info = CreateAbilityTransitionInfo(abilityToken, startOptions, want);
|
||
} else {
|
||
info = CreateAbilityTransitionInfo(abilityRequest, abilityToken);
|
||
}
|
||
auto pixelMap = DelayedSingleton<MissionInfoMgr>::GetInstance()->GetSnapshot(missionId);
|
||
if (!pixelMap) {
|
||
HILOG_WARN("%{public}s, Get snapshot failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
windowHandler->StartingWindow(info, pixelMap);
|
||
CancelStartingWindow(abilityToken, true);
|
||
}
|
||
|
||
void MissionListManager::CancelStartingWindow(const sptr<IRemoteObject> abilityToken, bool isDelay) const
|
||
{
|
||
HILOG_DEBUG("%{public}s, call CancelStartingWindow.", __func__);
|
||
auto windowHandler = GetWMSHandler();
|
||
if (!windowHandler) {
|
||
HILOG_ERROR("%{public}s, Get WMS handler failed.", __func__);
|
||
return;
|
||
}
|
||
|
||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||
if (handler == nullptr) {
|
||
HILOG_ERROR("Fail to get AbilityEventHandler.");
|
||
return;
|
||
}
|
||
|
||
auto task = [windowHandler, abilityToken] {
|
||
auto abilityRecord = Token::GetAbilityRecordByToken(abilityToken);
|
||
if (windowHandler && abilityRecord && abilityRecord->IsStartingWindow()) {
|
||
windowHandler->CancelStartingWindow(abilityToken);
|
||
abilityRecord->SetStartingWindow(false);
|
||
}
|
||
};
|
||
if (isDelay) {
|
||
int64_t delayTime = 5 * 1000;
|
||
handler->PostTask(task, delayTime);
|
||
} else {
|
||
handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::CompleteFirstFrameDrawing(const sptr<IRemoteObject> &abilityToken) const
|
||
{
|
||
if (!abilityToken) {
|
||
HILOG_WARN("%{public}s ability token is nullptr.", __func__);
|
||
return;
|
||
}
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityRecordByToken(abilityToken);
|
||
if (!abilityRecord) {
|
||
HILOG_WARN("%{public}s get AbilityRecord by token failed.", __func__);
|
||
return;
|
||
}
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionCreated(abilityRecord->GetMissionId());
|
||
}
|
||
}
|
||
#endif
|
||
|
||
void MissionListManager::Dump(std::vector<std::string> &info)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
std::string dumpInfo = "User ID #" + std::to_string(userId_);
|
||
info.push_back(dumpInfo);
|
||
dumpInfo = " current mission lists:{";
|
||
info.push_back(dumpInfo);
|
||
for (const auto& missionList : currentMissionLists_) {
|
||
if (missionList) {
|
||
missionList->Dump(info);
|
||
}
|
||
}
|
||
dumpInfo = " }";
|
||
info.push_back(dumpInfo);
|
||
|
||
dumpInfo = " default stand mission list:{";
|
||
info.push_back(dumpInfo);
|
||
if (defaultStandardList_) {
|
||
defaultStandardList_->Dump(info);
|
||
}
|
||
dumpInfo = " }";
|
||
info.push_back(dumpInfo);
|
||
|
||
dumpInfo = " default single mission list:{";
|
||
info.push_back(dumpInfo);
|
||
if (defaultSingleList_) {
|
||
defaultSingleList_->Dump(info);
|
||
}
|
||
dumpInfo = " }";
|
||
info.push_back(dumpInfo);
|
||
|
||
dumpInfo = " launcher mission list:{";
|
||
info.push_back(dumpInfo);
|
||
if (launcherList_) {
|
||
launcherList_->Dump(info);
|
||
}
|
||
dumpInfo = " }";
|
||
info.push_back(dumpInfo);
|
||
}
|
||
|
||
void MissionListManager::DumpMissionListByRecordId(
|
||
std::vector<std::string> &info, bool isClient, int32_t abilityRecordId, const std::vector<std::string> ¶ms)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
std::string dumpInfo = "User ID #" + std::to_string(userId_);
|
||
info.push_back(dumpInfo);
|
||
for (const auto& missionList : currentMissionLists_) {
|
||
if (missionList && missionList != launcherList_) {
|
||
HILOG_INFO("missionList begain to call DumpMissionListByRecordId %{public}s", __func__);
|
||
missionList->DumpStateByRecordId(info, isClient, abilityRecordId, params);
|
||
}
|
||
}
|
||
|
||
if (defaultStandardList_) {
|
||
HILOG_INFO("defaultStandardList begain to call DumpMissionListByRecordId %{public}s", __func__);
|
||
defaultStandardList_->DumpStateByRecordId(info, isClient, abilityRecordId, params);
|
||
}
|
||
|
||
if (defaultSingleList_) {
|
||
HILOG_INFO("defaultSingleList begain to call DumpMissionListByRecordId %{public}s", __func__);
|
||
defaultSingleList_->DumpStateByRecordId(info, isClient, abilityRecordId, params);
|
||
}
|
||
|
||
if (launcherList_) {
|
||
HILOG_INFO("launcherList begain to call DumpMissionListByRecordId %{public}s", __func__);
|
||
launcherList_->DumpStateByRecordId(info, isClient, abilityRecordId, params);
|
||
}
|
||
}
|
||
void MissionListManager::DumpMissionList(std::vector<std::string> &info, bool isClient, const std::string &args)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
if (args.size() != 0 &&
|
||
args != "NORMAL" &&
|
||
args != "DEFAULT_STANDARD" &&
|
||
args != "DEFAULT_SINGLE" &&
|
||
args != "LAUNCHER") {
|
||
info.emplace_back("MissionList Type NORMAL|DEFAULT_STANDARD|DEFAULT_SINGLE|LAUNCHER");
|
||
return;
|
||
}
|
||
|
||
std::string dumpInfo = "User ID #" + std::to_string(userId_);
|
||
info.push_back(dumpInfo);
|
||
if (args.size() == 0 || args == "NORMAL") {
|
||
dumpInfo = " Current mission lists:";
|
||
info.push_back(dumpInfo);
|
||
for (const auto& missionList : currentMissionLists_) {
|
||
if (missionList) {
|
||
missionList->DumpList(info, isClient);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (args.size() == 0 || args == "DEFAULT_STANDARD") {
|
||
dumpInfo = " default stand mission list:";
|
||
info.push_back(dumpInfo);
|
||
if (defaultStandardList_) {
|
||
defaultStandardList_->DumpList(info, isClient);
|
||
}
|
||
}
|
||
|
||
if (args.size() == 0 || args == "DEFAULT_SINGLE") {
|
||
dumpInfo = " default single mission list:";
|
||
info.push_back(dumpInfo);
|
||
if (defaultSingleList_) {
|
||
defaultSingleList_->DumpList(info, isClient);
|
||
}
|
||
}
|
||
if (args.size() == 0 || args == "LAUNCHER") {
|
||
dumpInfo = " launcher mission list:";
|
||
info.push_back(dumpInfo);
|
||
if (launcherList_) {
|
||
launcherList_->DumpList(info, isClient);
|
||
}
|
||
}
|
||
}
|
||
|
||
void MissionListManager::DumpMissionInfos(std::vector<std::string> &info)
|
||
{
|
||
std::string dumpInfo = "User ID #" + std::to_string(userId_);
|
||
info.push_back(dumpInfo);
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->Dump(info);
|
||
}
|
||
|
||
void MissionListManager::DumpMission(int missionId, std::vector<std::string> &info)
|
||
{
|
||
std::string dumpInfo = "User ID #" + std::to_string(userId_);
|
||
info.push_back(dumpInfo);
|
||
InnerMissionInfo innerMissionInfo;
|
||
if (DelayedSingleton<MissionInfoMgr>::GetInstance()->GetInnerMissionInfoById(missionId, innerMissionInfo) != 0) {
|
||
info.push_back("error: invalid mission number, please see 'aa dump --mission-list'.");
|
||
return;
|
||
}
|
||
innerMissionInfo.Dump(info);
|
||
}
|
||
|
||
int MissionListManager::ResolveLocked(const AbilityRequest &abilityRequest)
|
||
{
|
||
HILOG_INFO("%{public}s, resolve ability_name:%{public}s",
|
||
__func__,
|
||
abilityRequest.want.GetElement().GetURI().c_str());
|
||
|
||
if (!abilityRequest.IsCallType(AbilityCallType::CALL_REQUEST_TYPE)) {
|
||
HILOG_ERROR("%{public}s, resolve ability_name:", __func__);
|
||
return RESOLVE_CALL_ABILITY_INNER_ERR;
|
||
}
|
||
|
||
return CallAbilityLocked(abilityRequest);
|
||
}
|
||
|
||
int MissionListManager::CallAbilityLocked(const AbilityRequest &abilityRequest)
|
||
{
|
||
HILOG_INFO("call ability.");
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
// allow to start ability by called type without loading ui.
|
||
if (!abilityRequest.IsCallType(AbilityCallType::CALL_REQUEST_TYPE)) {
|
||
HILOG_ERROR("start ability not by call.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
// Get target mission and ability record.
|
||
std::shared_ptr<AbilityRecord> targetAbilityRecord;
|
||
std::shared_ptr<Mission> targetMission;
|
||
bool isCold = false;
|
||
GetTargetMissionAndAbility(abilityRequest, targetMission, targetAbilityRecord, isCold);
|
||
if (!targetMission || !targetAbilityRecord) {
|
||
HILOG_ERROR("Failed to get mission or record.");
|
||
return ERR_INVALID_VALUE;
|
||
}
|
||
|
||
targetAbilityRecord->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode);
|
||
targetAbilityRecord->SetLaunchReason(LaunchReason::LAUNCHREASON_CALL);
|
||
|
||
// mission is first created, add mission to default call mission list.
|
||
// other keep in current mission list.
|
||
if (!targetMission->GetMissionList()) {
|
||
defaultSingleList_->AddMissionToTop(targetMission);
|
||
}
|
||
|
||
// new version started by call type
|
||
auto ret = ResolveAbility(targetAbilityRecord, abilityRequest);
|
||
if (ret == ResolveResultType::OK_HAS_REMOTE_OBJ) {
|
||
HILOG_DEBUG("target ability has been resolved.");
|
||
return ERR_OK;
|
||
} else if (ret == ResolveResultType::NG_INNER_ERROR) {
|
||
HILOG_ERROR("resolve failed, error: %{public}d.", RESOLVE_CALL_ABILITY_INNER_ERR);
|
||
return RESOLVE_CALL_ABILITY_INNER_ERR;
|
||
}
|
||
|
||
// schedule target ability
|
||
std::string element = targetAbilityRecord->GetWant().GetElement().GetURI();
|
||
HILOG_DEBUG("load ability record: %{public}s", element.c_str());
|
||
|
||
// flag the first ability.
|
||
auto currentTopAbility = GetCurrentTopAbilityLocked();
|
||
if (!currentTopAbility) {
|
||
if (targetAbilityRecord->GetAbilityInfo().applicationInfo.isLauncherApp) {
|
||
targetAbilityRecord->SetLauncherRoot();
|
||
}
|
||
}
|
||
|
||
return targetAbilityRecord->LoadAbility();
|
||
}
|
||
|
||
int MissionListManager::ReleaseLocked(const sptr<IAbilityConnection> &connect, const AppExecFwk::ElementName &element)
|
||
{
|
||
HILOG_DEBUG("release ability.");
|
||
|
||
CHECK_POINTER_AND_RETURN(connect, ERR_INVALID_VALUE);
|
||
CHECK_POINTER_AND_RETURN(connect->AsObject(), ERR_INVALID_VALUE);
|
||
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
std::shared_ptr<AbilityRecord> abilityRecord = GetAbilityRecordByName(element);
|
||
CHECK_POINTER_AND_RETURN(abilityRecord, RELEASE_CALL_ABILITY_INNER_ERR);
|
||
|
||
if (!abilityRecord->Release(connect)) {
|
||
HILOG_ERROR("ability release call record failed.");
|
||
return RELEASE_CALL_ABILITY_INNER_ERR;
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
|
||
int MissionListManager::ResolveAbility(
|
||
const std::shared_ptr<AbilityRecord> &targetAbility, const AbilityRequest &abilityRequest)
|
||
{
|
||
HILOG_DEBUG("targetAbilityRecord resolve call record.");
|
||
CHECK_POINTER_AND_RETURN(targetAbility, ResolveResultType::NG_INNER_ERROR);
|
||
|
||
ResolveResultType result = targetAbility->Resolve(abilityRequest);
|
||
switch (result) {
|
||
case ResolveResultType::NG_INNER_ERROR:
|
||
case ResolveResultType::OK_HAS_REMOTE_OBJ:
|
||
return result;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (targetAbility->IsReady()) {
|
||
HILOG_DEBUG("targetAbility is ready, directly scheduler call request.");
|
||
if (targetAbility->CallRequest()) {
|
||
return ResolveResultType::OK_HAS_REMOTE_OBJ;
|
||
}
|
||
}
|
||
|
||
HILOG_DEBUG("targetAbility need to call request after lifecycle.");
|
||
return result;
|
||
}
|
||
|
||
std::shared_ptr<AbilityRecord> MissionListManager::GetAbilityRecordByName(const AppExecFwk::ElementName &element)
|
||
{
|
||
// find in currentMissionLists_
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList != nullptr) {
|
||
auto ability = missionList->GetAbilityRecordByName(element);
|
||
if (ability != nullptr) {
|
||
return ability;
|
||
}
|
||
}
|
||
}
|
||
|
||
// find in lanucheMissionList_
|
||
auto ability = launcherList_->GetAbilityRecordByName(element);
|
||
if (ability != nullptr) {
|
||
return ability;
|
||
}
|
||
|
||
// find in default singlelist_
|
||
return defaultSingleList_->GetAbilityRecordByName(element);
|
||
}
|
||
|
||
void MissionListManager::OnCallConnectDied(const std::shared_ptr<CallRecord> &callRecord)
|
||
{
|
||
HILOG_INFO("On callConnect died.");
|
||
CHECK_POINTER(callRecord);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
AppExecFwk::ElementName element = callRecord->GetTargetServiceName();
|
||
auto abilityRecord = GetAbilityRecordByName(element);
|
||
CHECK_POINTER(abilityRecord);
|
||
abilityRecord->Release(callRecord->GetConCallBack());
|
||
}
|
||
void MissionListManager::OnAcceptWantResponse(const AAFwk::Want &want, const std::string &flag)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (waittingAbilityQueue_.empty()) {
|
||
return;
|
||
}
|
||
|
||
AbilityRequest abilityRequest = waittingAbilityQueue_.front();
|
||
waittingAbilityQueue_.pop();
|
||
|
||
auto currentTopAbility = GetCurrentTopAbilityLocked();
|
||
auto callerAbility = GetAbilityRecordByToken(abilityRequest.callerToken);
|
||
|
||
if (!flag.empty()) {
|
||
auto mission = GetMissionBySpecifiedFlag(want, flag);
|
||
if (mission) {
|
||
auto ability = mission->GetAbilityRecord();
|
||
if (!ability) {
|
||
return;
|
||
}
|
||
ability->SetWant(abilityRequest.want);
|
||
ability->SetIsNewWant(true);
|
||
|
||
auto isCallerFromLauncher = (callerAbility && callerAbility->IsLauncherAbility());
|
||
MoveMissionToFront(mission->GetMissionId(), isCallerFromLauncher);
|
||
return;
|
||
}
|
||
}
|
||
|
||
abilityRequest.specifiedFlag = flag;
|
||
StartAbilityLocked(currentTopAbility, callerAbility, abilityRequest);
|
||
}
|
||
|
||
void MissionListManager::OnStartSpecifiedAbilityTimeoutResponse(const AAFwk::Want &want)
|
||
{
|
||
HILOG_DEBUG("%{public}s called.", __func__);
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
if (waittingAbilityQueue_.empty()) {
|
||
return;
|
||
}
|
||
waittingAbilityQueue_.pop();
|
||
|
||
if (waittingAbilityQueue_.empty()) {
|
||
return;
|
||
}
|
||
AbilityRequest abilityRequest = waittingAbilityQueue_.front();
|
||
waittingAbilityQueue_.pop();
|
||
|
||
auto currentTopAbility = GetCurrentTopAbilityLocked();
|
||
auto callerAbility = GetAbilityRecordByToken(abilityRequest.callerToken);
|
||
StartAbility(currentTopAbility, callerAbility, abilityRequest);
|
||
}
|
||
|
||
std::shared_ptr<Mission> MissionListManager::GetMissionBySpecifiedFlag(
|
||
const AAFwk::Want &want, const std::string &flag) const
|
||
{
|
||
std::shared_ptr<Mission> mission = nullptr;
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (missionList && (mission = missionList->GetMissionBySpecifiedFlag(want, flag)) != nullptr) {
|
||
return mission;
|
||
}
|
||
}
|
||
|
||
if ((mission = defaultSingleList_->GetMissionBySpecifiedFlag(want, flag)) != nullptr) {
|
||
return mission;
|
||
}
|
||
|
||
if ((mission = launcherList_->GetMissionBySpecifiedFlag(want, flag)) != nullptr) {
|
||
return mission;
|
||
}
|
||
|
||
return defaultStandardList_->GetMissionBySpecifiedFlag(want, flag);
|
||
}
|
||
|
||
bool MissionListManager::MissionDmInitCallback::isInit_ = false;
|
||
void MissionListManager::MissionDmInitCallback::OnRemoteDied()
|
||
{
|
||
isInit_ = false;
|
||
HILOG_WARN("DeviceManager died.");
|
||
}
|
||
|
||
void MissionListManager::RegisterSnapshotHandler(const sptr<ISnapshotHandler>& handler)
|
||
{
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->RegisterSnapshotHandler(handler);
|
||
}
|
||
|
||
bool MissionListManager::GetMissionSnapshot(int32_t missionId, const sptr<IRemoteObject>& abilityToken,
|
||
MissionSnapshot& missionSnapshot)
|
||
{
|
||
HILOG_INFO("snapshot: Start get mission snapshot.");
|
||
bool forceSnapshot = false;
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto abilityRecord = GetAbilityRecordByToken(abilityToken);
|
||
if (abilityRecord && abilityRecord->IsAbilityState(FOREGROUND)) {
|
||
forceSnapshot = true;
|
||
}
|
||
}
|
||
return DelayedSingleton<MissionInfoMgr>::GetInstance()->GetMissionSnapshot(
|
||
missionId, abilityToken, missionSnapshot, forceSnapshot);
|
||
}
|
||
|
||
void MissionListManager::GetAbilityRunningInfos(std::vector<AbilityRunningInfo> &info, bool isPerm)
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
|
||
auto func = [&info, isPerm](const std::shared_ptr<Mission> &mission) {
|
||
if (!mission) {
|
||
return;
|
||
}
|
||
|
||
auto ability = mission->GetAbilityRecord();
|
||
if (!ability) {
|
||
return;
|
||
}
|
||
|
||
if (isPerm) {
|
||
DelayedSingleton<AbilityManagerService>::GetInstance()->GetAbilityRunningInfo(info, ability);
|
||
} else {
|
||
auto callingTokenId = IPCSkeleton::GetCallingTokenID();
|
||
auto tokenID = ability->GetApplicationInfo().accessTokenId;
|
||
if (callingTokenId == tokenID) {
|
||
DelayedSingleton<AbilityManagerService>::GetInstance()->GetAbilityRunningInfo(info, ability);
|
||
}
|
||
}
|
||
};
|
||
if (!(defaultStandardList_->GetAllMissions().empty())) {
|
||
auto list = defaultStandardList_->GetAllMissions();
|
||
std::for_each(list.begin(), list.end(), func);
|
||
}
|
||
if (!(defaultSingleList_->GetAllMissions().empty())) {
|
||
auto list = defaultSingleList_->GetAllMissions();
|
||
std::for_each(list.begin(), list.end(), func);
|
||
}
|
||
for (auto missionList : currentMissionLists_) {
|
||
if (!(missionList->GetAllMissions().empty())) {
|
||
auto list = missionList->GetAllMissions();
|
||
std::for_each(list.begin(), list.end(), func);
|
||
}
|
||
}
|
||
}
|
||
|
||
void MissionListManager::UninstallApp(const std::string &bundleName, int32_t uid)
|
||
{
|
||
HILOG_INFO("Uninstall app, bundleName: %{public}s, uid:%{public}d", bundleName.c_str(), uid);
|
||
auto abilityManagerService = DelayedSingleton<AbilityManagerService>::GetInstance();
|
||
CHECK_POINTER(abilityManagerService);
|
||
auto handler = abilityManagerService->GetEventHandler();
|
||
CHECK_POINTER(handler);
|
||
std::weak_ptr<MissionListManager> wpMgr = shared_from_this();
|
||
auto task = [wpMgr, bundleName, uid]() {
|
||
HILOG_INFO("Handle Uninstall app, bundleName: %{public}s, uid:%{public}d", bundleName.c_str(), uid);
|
||
auto mgr = wpMgr.lock();
|
||
if (mgr) {
|
||
mgr->AddUninstallTags(bundleName, uid);
|
||
}
|
||
};
|
||
handler->PostTask(task);
|
||
}
|
||
|
||
void MissionListManager::AddUninstallTags(const std::string &bundleName, int32_t uid)
|
||
{
|
||
HILOG_INFO("AddUninstallTags, bundleName: %{public}s, uid:%{public}d", bundleName.c_str(), uid);
|
||
for (auto it = currentMissionLists_.begin(); it != currentMissionLists_.end();) {
|
||
auto missionList = *it;
|
||
if (missionList) {
|
||
missionList->HandleUnInstallApp(bundleName, uid); // add tag here.
|
||
if (missionList->IsEmpty()) {
|
||
currentMissionLists_.erase(it++);
|
||
continue;
|
||
}
|
||
}
|
||
it++;
|
||
}
|
||
defaultSingleList_->HandleUnInstallApp(bundleName, uid);
|
||
defaultStandardList_->HandleUnInstallApp(bundleName, uid);
|
||
std::list<int32_t> matchedMissions;
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->HandleUnInstallApp(bundleName, uid, matchedMissions);
|
||
if (listenerController_) {
|
||
listenerController_->HandleUnInstallApp(matchedMissions);
|
||
}
|
||
}
|
||
|
||
bool MissionListManager::IsStarted()
|
||
{
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
auto launcherRoot = launcherList_->GetLauncherRoot();
|
||
return launcherRoot != nullptr;
|
||
}
|
||
|
||
void MissionListManager::PauseManager()
|
||
{
|
||
HILOG_INFO("MissionListManager PauseManager. move foreground to background.");
|
||
std::lock_guard<std::recursive_mutex> guard(managerLock_);
|
||
std::list<std::shared_ptr<AbilityRecord>> foregroundAbilities;
|
||
GetAllForegroundAbilities(foregroundAbilities);
|
||
|
||
for (auto& abilityRecord : foregroundAbilities) {
|
||
if (!abilityRecord) {
|
||
continue;
|
||
}
|
||
abilityRecord->SetSwitchingPause(true);
|
||
MoveToBackgroundTask(abilityRecord);
|
||
}
|
||
}
|
||
|
||
void MissionListManager::ResumeManager()
|
||
{
|
||
HILOG_INFO("ResumeManager, back to launcher.");
|
||
BackToLauncher();
|
||
}
|
||
|
||
void MissionListManager::GetAllForegroundAbilities(std::list<std::shared_ptr<AbilityRecord>>& foregroundList)
|
||
{
|
||
std::shared_ptr<AbilityRecord> abilityRecord = nullptr;
|
||
for (auto& missionList : currentMissionLists_) {
|
||
GetForegroundAbilities(missionList, foregroundList);
|
||
}
|
||
GetForegroundAbilities(defaultSingleList_, foregroundList);
|
||
GetForegroundAbilities(defaultStandardList_, foregroundList);
|
||
}
|
||
|
||
void MissionListManager::GetForegroundAbilities(const std::shared_ptr<MissionList>& missionList,
|
||
std::list<std::shared_ptr<AbilityRecord>>& foregroundList)
|
||
{
|
||
if (!missionList || missionList->IsEmpty()) {
|
||
return;
|
||
}
|
||
|
||
for (auto& mission : missionList->GetAllMissions()) {
|
||
if (!mission) {
|
||
continue;
|
||
}
|
||
|
||
auto abilityRecord = mission->GetAbilityRecord();
|
||
if (!abilityRecord) {
|
||
continue;
|
||
}
|
||
|
||
if (abilityRecord->IsActiveState()) {
|
||
foregroundList.emplace_back(abilityRecord);
|
||
}
|
||
}
|
||
}
|
||
|
||
void MissionListManager::RemoveMissionLocked(int32_t missionId)
|
||
{
|
||
if (missionId <= 0) {
|
||
return;
|
||
}
|
||
|
||
DelayedSingleton<MissionInfoMgr>::GetInstance()->DeleteMissionInfo(missionId);
|
||
if (listenerController_) {
|
||
listenerController_->NotifyMissionDestroyed(missionId);
|
||
}
|
||
}
|
||
|
||
#ifdef ABILITY_COMMAND_FOR_TEST
|
||
int MissionListManager::BlockAbility(int32_t abilityRecordId)
|
||
{
|
||
int ret = -1;
|
||
for (const auto &missionList : currentMissionLists_) {
|
||
if (missionList && missionList != launcherList_) {
|
||
HILOG_INFO("missionList begain to call BlockAbilityByRecordId %{public}s", __func__);
|
||
if (missionList->BlockAbilityByRecordId(abilityRecordId) == ERR_OK) {
|
||
HILOG_INFO("missionList call BlockAbilityByRecordId success");
|
||
ret = ERR_OK;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (defaultStandardList_) {
|
||
HILOG_INFO("defaultStandardList begain to call BlockAbilityByRecordId %{public}s", __func__);
|
||
if (defaultStandardList_->BlockAbilityByRecordId(abilityRecordId) == ERR_OK) {
|
||
HILOG_INFO("defaultStandardList call BlockAbilityByRecordId success");
|
||
ret = ERR_OK;
|
||
}
|
||
}
|
||
|
||
if (defaultSingleList_) {
|
||
HILOG_INFO("defaultSingleList begain to call BlockAbilityByRecordId %{public}s", __func__);
|
||
if (defaultSingleList_->BlockAbilityByRecordId(abilityRecordId) == ERR_OK) {
|
||
HILOG_INFO("defaultSingleList_ call BlockAbilityByRecordId success");
|
||
ret = ERR_OK;
|
||
}
|
||
}
|
||
|
||
if (launcherList_) {
|
||
HILOG_INFO("launcherList begain to call BlockAbilityByRecordId %{public}s", __func__);
|
||
if (launcherList_->BlockAbilityByRecordId(abilityRecordId) == ERR_OK) {
|
||
HILOG_INFO("launcherList_ call BlockAbilityByRecordId success");
|
||
ret = ERR_OK;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
#endif
|
||
} // namespace AAFwk
|
||
} // namespace OHOS
|