/* * Copyright (c) 2021 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 "kernal_system_app_manager.h" #include "hilog_wrapper.h" #include "ability_util.h" #include "ability_manager_errors.h" #include "ability_manager_service.h" #include "app_scheduler.h" namespace OHOS { namespace AAFwk { KernalSystemAppManager::KernalSystemAppManager(int userId) : userId_(userId) {} KernalSystemAppManager::~KernalSystemAppManager() {} int KernalSystemAppManager::StartAbility(const AbilityRequest &abilityRequest) { HILOG_INFO("start kernal systerm ability."); std::lock_guard guard(stackLock_); if (!waittingAbilityQueue_.empty()) { HILOG_INFO("waiting queue is not empty, so enqueue systerm ui ability for waiting."); EnqueueWaittingAbility(abilityRequest); return START_ABILITY_WAITING; } std::shared_ptr topAbilityRecord = GetCurrentTopAbility(); auto requestFlag = GetFlagOfAbility(abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); if (topAbilityRecord != nullptr) { auto topFlag = GetFlagOfAbility(topAbilityRecord->GetAbilityInfo().bundleName, topAbilityRecord->GetAbilityInfo().name); if (topFlag == requestFlag && topAbilityRecord->GetAbilityState() == INITIAL) { HILOG_INFO("top systerm ui ability need to restart."); } if (topAbilityRecord->GetAbilityState() == ACTIVATING) { HILOG_INFO("top systerm ui ability is not active, so enqueue ability for waiting."); EnqueueWaittingAbility(abilityRequest); return START_ABILITY_WAITING; } } return StartAbilityLocked(abilityRequest); } int KernalSystemAppManager::StartAbilityLocked(const AbilityRequest &abilityRequest) { std::shared_ptr targetAbility; GetOrCreateAbilityRecord(abilityRequest, targetAbility); CHECK_POINTER_AND_RETURN(targetAbility, ERR_INVALID_VALUE); targetAbility->SetKernalSystemAbility(); HILOG_INFO("Load kernal system ability, bundleName:%{public}s , abilityName:%{public}s", abilityRequest.abilityInfo.bundleName.c_str(), abilityRequest.abilityInfo.name.c_str()); if (targetAbility->IsAbilityState(AbilityState::ACTIVE) || targetAbility->IsAbilityState(AbilityState::ACTIVATING)) { HILOG_INFO("kernal system ability is already activing or activated."); targetAbility->Activate(); return ERR_OK; } return targetAbility->LoadAbility(); } int KernalSystemAppManager::AttachAbilityThread( const sptr &scheduler, const sptr &token) { HILOG_INFO("Attach ability thread."); std::lock_guard guard(stackLock_); auto abilityRecord = GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string flag = KernalSystemAppManager::GetFlagOfAbility( abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name); HILOG_INFO("ability: %{public}s", flag.c_str()); auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); CHECK_POINTER_AND_RETURN(handler, ERR_INVALID_VALUE); handler->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId()); abilityRecord->SetScheduler(scheduler); DelayedSingleton::GetInstance()->MoveToForground(token); return ERR_OK; } void KernalSystemAppManager::OnAbilityRequestDone(const sptr &token, const int32_t state) { HILOG_INFO("On ability request done."); std::lock_guard guard(stackLock_); AppAbilityState abilitState = DelayedSingleton::GetInstance()->ConvertToAppAbilityState(state); if (abilitState == AppAbilityState::ABILITY_STATE_FOREGROUND) { auto abilityRecord = GetAbilityRecordByToken(token); CHECK_POINTER(abilityRecord); abilityRecord->Activate(); } } void KernalSystemAppManager::OnAppStateChanged(const AppInfo &info) { std::lock_guard guard(stackLock_); for (auto ability : abilities_) { if (ability && ability->GetApplicationInfo().name == info.appName && (info.processName == ability->GetAbilityInfo().process || info.processName == ability->GetApplicationInfo().bundleName)) { ability->SetAppState(info.state); } } } int KernalSystemAppManager::AbilityTransitionDone(const sptr &token, int state) { HILOG_INFO("Ability transition done."); std::lock_guard guard(stackLock_); auto abilityRecord = GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string flag = KernalSystemAppManager::GetFlagOfAbility( abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name); int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(state)); std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast(targetState)); HILOG_INFO("ability: %{public}s, state: %{public}s", flag.c_str(), abilityState.c_str()); switch (targetState) { case AbilityState::ACTIVE: { return DispatchActive(abilityRecord, targetState); } default: { HILOG_WARN("don't support transiting state: %d", targetState); return ERR_INVALID_VALUE; } } } int KernalSystemAppManager::DispatchActive(const std::shared_ptr &abilityRecord, int state) { auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); CHECK_POINTER_AND_RETURN(handler, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); if (!abilityRecord->IsAbilityState(AbilityState::ACTIVATING)) { HILOG_ERROR("kernal ability transition life state error. start:%{public}d", state); return ERR_INVALID_VALUE; } handler->RemoveEvent(AbilityManagerService::ACTIVE_TIMEOUT_MSG, abilityRecord->GetEventId()); auto task = [kernalManager = shared_from_this(), abilityRecord]() { kernalManager->CompleteActive(abilityRecord); }; handler->PostTask(task); return ERR_OK; } void KernalSystemAppManager::CompleteActive(const std::shared_ptr &abilityRecord) { HILOG_INFO("Complete active."); std::lock_guard guard(stackLock_); abilityRecord->SetAbilityState(AbilityState::ACTIVE); auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); CHECK_POINTER(handler); auto task = [kernalManager = shared_from_this()]() { kernalManager->DequeueWaittingAbility(); }; handler->PostTask(task, "DequeueWaittingAbility"); } void KernalSystemAppManager::GetOrCreateAbilityRecord( const AbilityRequest &abilityRequest, std::shared_ptr &targetAbility) { std::string abilityFlag = KernalSystemAppManager::GetFlagOfAbility( abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); auto isExist = [targetFlag = abilityFlag](const std::shared_ptr &ability) { if (ability == nullptr) { return false; } return KernalSystemAppManager::GetFlagOfAbility( ability->GetAbilityInfo().bundleName, ability->GetAbilityInfo().name) == targetFlag; }; auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); if (iter != abilities_.end()) { targetAbility = *iter; targetAbility->SetWant(abilityRequest.want); targetAbility->SetIsNewWant(true); return; } targetAbility = AbilityRecord::CreateAbilityRecord(abilityRequest); auto configSptr = std::make_shared(); targetAbility->SetConfiguration(configSptr); abilities_.push_front(targetAbility); } std::string KernalSystemAppManager::GetFlagOfAbility(const std::string &bundleName, const std::string &abilityName) { return bundleName + ":" + abilityName; } int KernalSystemAppManager::GetManagerUserId() const { return userId_; } std::shared_ptr KernalSystemAppManager::GetCurrentTopAbility() const { if (abilities_.empty()) { return nullptr; } return abilities_.front(); } std::shared_ptr KernalSystemAppManager::GetAbilityRecordByToken(const sptr &token) { std::lock_guard guard(stackLock_); auto abilityToFind = Token::GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityToFind, nullptr); auto isExist = [targetAbility = abilityToFind](const std::shared_ptr &ability) { if (ability == nullptr) { return false; } return targetAbility == ability; }; auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); if (iter != abilities_.end()) { return *iter; } return nullptr; } std::shared_ptr KernalSystemAppManager::GetAbilityRecordByEventId(const int64_t eventId) const { auto isExist = [targetEventId = eventId](const std::shared_ptr &ability) { if (ability == nullptr) { return false; } return (ability->GetEventId() == targetEventId); }; auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); if (iter != abilities_.end()) { return *iter; } return nullptr; } bool KernalSystemAppManager::RemoveAbilityRecord(std::shared_ptr ability) { CHECK_POINTER_RETURN_BOOL(ability); for (auto iter = abilities_.begin(); iter != abilities_.end(); iter++) { if ((*iter) == ability) { abilities_.erase(iter); return true; } } HILOG_ERROR("can not find ability"); return false; } void KernalSystemAppManager::EnqueueWaittingAbility(const AbilityRequest &abilityRequest) { waittingAbilityQueue_.push(abilityRequest); return; } void KernalSystemAppManager::DequeueWaittingAbility() { std::lock_guard guard(stackLock_); std::shared_ptr topAbility = GetCurrentTopAbility(); if (topAbility != nullptr && topAbility->GetAbilityState() != ACTIVE) { HILOG_INFO("top ability is not active, must return for waiting again"); return; } if (!waittingAbilityQueue_.empty()) { AbilityRequest abilityRequest = waittingAbilityQueue_.front(); waittingAbilityQueue_.pop(); HILOG_INFO("bundleName: %{public}s, abilityName: %{public}s", abilityRequest.abilityInfo.bundleName.c_str(), abilityRequest.abilityInfo.name.c_str()); StartAbilityLocked(abilityRequest); } } void KernalSystemAppManager::DumpState(std::vector &info) { info.emplace_back("SystemUIRecords:"); for (auto &ability : abilities_) { ability->Dump(info); } } void KernalSystemAppManager::OnAbilityDied(std::shared_ptr abilityRecord) { std::lock_guard guard(stackLock_); CHECK_POINTER(abilityRecord); if (!abilityRecord->IsKernalSystemAbility()) { HILOG_ERROR("System UI on scheduler died, ability type is not system ui"); return; } if (GetAbilityRecordByToken(abilityRecord->GetToken()) == nullptr) { HILOG_ERROR("System UI on scheduler died, record is not exist."); return; } auto ams = DelayedSingleton::GetInstance(); CHECK_POINTER(ams); auto handler = ams->GetEventHandler(); CHECK_POINTER(handler); HILOG_INFO("System UI on scheduler died: '%{public}s'", abilityRecord->GetAbilityInfo().name.c_str()); std::string name = abilityRecord->GetAbilityInfo().name; abilityRecord->SetAbilityState(AbilityState::INITIAL); auto timeoutTask = [ams, abilityRecord]() { if (abilityRecord) { ams->StartSystemUi(abilityRecord->GetAbilityInfo().name); } }; handler->PostTask(timeoutTask, "SystemUi_Die_" + name, AbilityManagerService::RESTART_TIMEOUT); } void KernalSystemAppManager::OnTimeOut(uint32_t msgId, int64_t eventId) { std::lock_guard guard(stackLock_); if (abilities_.empty()) { HILOG_ERROR("System UI on time out event: ability stack is empty."); return; } auto abilityRecord = GetAbilityRecordByEventId(eventId); CHECK_POINTER(abilityRecord); auto ams = DelayedSingleton::GetInstance(); CHECK_POINTER(ams); auto handler = ams->GetEventHandler(); CHECK_POINTER(handler); switch (msgId) { case AbilityManagerService::LOAD_TIMEOUT_MSG: case AbilityManagerService::ACTIVE_TIMEOUT_MSG: { std::string bundleName = abilityRecord->GetAbilityInfo().bundleName; std::string name = abilityRecord->GetAbilityInfo().name; RemoveAbilityRecord(abilityRecord); auto task = [ams, bundleName]() { ams->KillProcess(bundleName); HILOG_ERROR("System UI on time out event: KillProcess:%{public}s", bundleName.c_str()); }; handler->PostTask(task); auto timeoutTask = [ams, name]() { ams->StartSystemUi(name); HILOG_ERROR("System UI on time out event: restart:%{public}s", name.c_str()); }; handler->PostTask(timeoutTask, "SystemUi_Timeout_" + name, AbilityManagerService::RESTART_TIMEOUT); break; } default: break; } } int KernalSystemAppManager::UpdateConfiguration(const DummyConfiguration &config) { std::lock_guard guard(stackLock_); std::shared_ptr configPtr = std::make_shared(config); for (auto &ability : abilities_) { if (ability) { if (ability->IsAbilityState(AbilityState::ACTIVE)) { HILOG_DEBUG("system ui update configuration."); ability->ForceProcessConfigurationChange(configPtr); } } } return ERR_OK; } void KernalSystemAppManager::RestartAbility(const std::shared_ptr abilityRecord) { CHECK_POINTER(abilityRecord); HILOG_DEBUG("Restart ability system ui. %{public}s", abilityRecord->GetAbilityInfo().name.c_str()); return; } } // namespace AAFwk } // namespace OHOS