* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "app_preloader.h"
#include <string>
#include "ability_manager_errors.h"
#include "in_process_call_wrapper.h"
#include "hilog_tag_wrapper.h"
#include "hitrace_meter.h"
#include "res_sched_client.h"
#include "res_type.h"
#include "startup_util.h"
namespace OHOS {
namespace AppExecFwk {
AppPreloader::AppPreloader(std::shared_ptr<RemoteClientManager> remoteClientManager)
{
remoteClientManager_ = remoteClientManager;
}
bool AppPreloader::PreCheck(const std::string &bundleName, PreloadMode preloadMode)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication PreCheck, bundleName: %{public}s, preloadMode:%{public}d",
bundleName.c_str(), preloadMode);
if (preloadMode == PreloadMode::PRE_MAKE ||
preloadMode == PreloadMode::PRELOAD_MODULE ||
preloadMode == PreloadMode::PRELOAD_BY_PHASE) {
return true;
}
int32_t mode = static_cast<int32_t>(preloadMode);
auto allow = ResourceSchedule::ResSchedClient::GetInstance().IsAllowedAppPreload(bundleName, mode);
if (!allow) {
TAG_LOGI(AAFwkTag::APPMGR, "BundleName: %{public}s not allow preload", bundleName.c_str());
return false;
}
return true;
}
int32_t AppPreloader::GeneratePreloadRequest(const std::string &bundleName, int32_t userId, int32_t appIndex,
PreloadRequest &request)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication GeneratePreloadRequest");
AAFwk::Want launchWant;
if (!GetLaunchWant(bundleName, userId, launchWant)) {
TAG_LOGE(AAFwkTag::APPMGR, "GetLaunchWant failed");
return AAFwk::ERR_TARGET_BUNDLE_NOT_EXIST;
}
AbilityInfo abilityInfo;
if (!GetLaunchAbilityInfo(launchWant, userId, abilityInfo)) {
TAG_LOGE(AAFwkTag::APPMGR, "GetLaunchAbilityInfo failed");
return AAFwk::ERR_GET_LAUNCH_ABILITY_INFO_FAILED;
}
if (!CheckPreloadConditions(abilityInfo)) {
TAG_LOGE(AAFwkTag::APPMGR, "CheckPreloadConditions failed");
return AAFwk::ERR_CHECK_PRELOAD_CONDITIONS_FAILED;
}
BundleInfo bundleInfo;
HapModuleInfo hapModuleInfo;
if (!GetBundleAndHapInfo(bundleName, userId, abilityInfo, bundleInfo, hapModuleInfo)) {
TAG_LOGE(AAFwkTag::APPMGR, "GetBundleAndHapInfo failed");
return AAFwk::GET_BUNDLE_INFO_FAILED;
}
if (request.preloadMode == PreloadMode::PRELOAD_BY_PHASE &&
hapModuleInfo.moduleType != AppExecFwk::ModuleType::ENTRY) {
TAG_LOGE(AAFwkTag::APPMGR, "Not entry module.");
return AAFwk::ERR_PRELOAD_NOT_ENTRY_MODULE;
}
request.abilityInfo = std::make_shared<AbilityInfo>(abilityInfo);
request.appInfo = std::make_shared<ApplicationInfo>(abilityInfo.applicationInfo);
request.want = std::make_shared<AAFwk::Want>(launchWant);
request.bundleInfo = bundleInfo;
request.hapModuleInfo = hapModuleInfo;
request.appIndex = appIndex;
return ERR_OK;
}
bool AppPreloader::GetLaunchWant(const std::string &bundleName, int32_t userId, AAFwk::Want &launchWant)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
auto bundleMgrHelper = GetBundleManagerHelper();
if (!bundleMgrHelper) {
TAG_LOGE(AAFwkTag::APPMGR, "null bundleMgrHelper");
return false;
}
TAG_LOGD(AAFwkTag::APPMGR, "userId: %{public}d, bundleName: %{public}s", userId, bundleName.c_str());
auto errCode = IN_PROCESS_CALL(bundleMgrHelper->GetLaunchWantForBundle(bundleName, launchWant, userId));
if (errCode != ERR_OK) {
TAG_LOGE(AAFwkTag::APPMGR, "errCode: %{public}d", errCode);
return false;
}
return true;
}
bool AppPreloader::GetAbilityInfo(const AAFwk::Want &want, int32_t userId, int32_t appIndex,
PreloadRequest &request, AbilityInfo &abilityInfo)
{
auto bundleMgrHelper = GetBundleManagerHelper();
if (!bundleMgrHelper) {
TAG_LOGE(AAFwkTag::APPMGR, "get bundle manager helper error");
return false;
}
auto abilityInfoFlag = AbilityRuntime::StartupUtil::BuildAbilityInfoFlag();
if (IN_PROCESS_CALL(bundleMgrHelper->QueryAbilityInfo(want, abilityInfoFlag, userId, abilityInfo))) {
TAG_LOGI(AAFwkTag::APPMGR, "queryAbilityInfo ok");
return true;
}
std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
if (appIndex == 0) {
if (!IN_PROCESS_CALL(bundleMgrHelper->QueryExtensionAbilityInfos(want, abilityInfoFlag,
userId, extensionInfos))) {
TAG_LOGE(AAFwkTag::APPMGR, "queryExtensionAbilityInfos fail");
return false;
}
} else {
if (IN_PROCESS_CALL(bundleMgrHelper->GetSandboxExtAbilityInfos(want, appIndex,
abilityInfoFlag, userId, extensionInfos) != ERR_OK)) {
TAG_LOGE(AAFwkTag::APPMGR, "getSandboxExtAbilityInfos fail");
return false;
}
}
if (extensionInfos.size() <= 0) {
TAG_LOGE(AAFwkTag::APPMGR, "get extension info fail");
return false;
}
AppExecFwk::ExtensionAbilityInfo extensionInfo = extensionInfos.front();
request.extensionProcessMode = extensionInfo.extensionProcessMode;
AbilityRuntime::StartupUtil::InitAbilityInfoFromExtension(extensionInfo, abilityInfo);
return true;
}
int32_t AppPreloader::GeneratePreloadExtensionRequest(const AAFwk::Want &want,
int32_t userId, int32_t appIndex, PreloadRequest &request)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
TAG_LOGD(AAFwkTag::APPMGR, "PreloadExtension GeneratePreloadRequest");
AbilityInfo abilityInfo;
if (!GetAbilityInfo(want, userId, appIndex, request, abilityInfo)) {
TAG_LOGE(AAFwkTag::APPMGR, "createAbilityInfo fail");
return ERR_INVALID_OPERATION;
}
std::string bundleName = want.GetElement().GetBundleName();
BundleInfo bundleInfo;
HapModuleInfo hapModuleInfo;
if (!GetBundleAndHapInfo(bundleName, userId, abilityInfo, bundleInfo, hapModuleInfo)) {
TAG_LOGE(AAFwkTag::APPMGR, "GetBundleAndHapInfo failed");
return AAFwk::GET_BUNDLE_INFO_FAILED;
}
request.abilityInfo = std::make_shared<AbilityInfo>(abilityInfo);
request.appInfo = std::make_shared<ApplicationInfo>(abilityInfo.applicationInfo);
request.want = std::make_shared<AAFwk::Want>(want);
request.bundleInfo = bundleInfo;
request.hapModuleInfo = hapModuleInfo;
request.appIndex = appIndex;
return ERR_OK;
}
bool AppPreloader::GetLaunchAbilityInfo(const AAFwk::Want &want, int32_t userId, AbilityInfo &abilityInfo)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
auto bundleMgrHelper = GetBundleManagerHelper();
if (!bundleMgrHelper) {
TAG_LOGE(AAFwkTag::APPMGR, "null bundleMgrHelper");
return false;
}
TAG_LOGD(AAFwkTag::APPMGR, "userId: %{public}d", userId);
auto abilityInfoFlag = AbilityRuntime::StartupUtil::BuildAbilityInfoFlag();
if (!IN_PROCESS_CALL(bundleMgrHelper->QueryAbilityInfo(want, abilityInfoFlag, userId, abilityInfo))) {
TAG_LOGE(AAFwkTag::APPMGR, "GetLaunchAbilityInfo failed");
return false;
}
return true;
}
bool AppPreloader::GetBundleAndHapInfo(const std::string &bundleName, int32_t userId,
const AbilityInfo &abilityInfo, BundleInfo &bundleInfo, HapModuleInfo &hapModuleInfo)
{
HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
auto bundleMgrHelper = GetBundleManagerHelper();
if (!bundleMgrHelper) {
TAG_LOGE(AAFwkTag::APPMGR, "null bundleMgrHelper");
return false;
}
TAG_LOGD(AAFwkTag::APPMGR, "userId: %{public}d, bundleName: %{public}s", userId, bundleName.c_str());
if (!IN_PROCESS_CALL(bundleMgrHelper->GetBundleInfo(bundleName,
BundleFlag::GET_BUNDLE_WITH_REQUESTED_PERMISSION,
bundleInfo, userId))) {
TAG_LOGE(AAFwkTag::APPMGR, "GetBundleInfo failed");
return false;
}
if (!IN_PROCESS_CALL(bundleMgrHelper->GetHapModuleInfo(abilityInfo, userId, hapModuleInfo))) {
TAG_LOGE(AAFwkTag::APPMGR, "GetHapModuleInfo failed");
return false;
}
return true;
}
bool AppPreloader::CheckPreloadConditions(const AbilityInfo &abilityInfo)
{
if (abilityInfo.type != AppExecFwk::AbilityType::PAGE || !abilityInfo.isStageBasedModel) {
TAG_LOGE(AAFwkTag::APPMGR, "AbilityType is not UIAbility");
return false;
}
ApplicationInfo appInfo = abilityInfo.applicationInfo;
if (abilityInfo.name.empty() || appInfo.name.empty()) {
TAG_LOGE(AAFwkTag::APPMGR, "abilityInfo or appInfo name is empty");
return false;
}
if (abilityInfo.applicationName != appInfo.name) {
TAG_LOGE(AAFwkTag::APPMGR, "abilityInfo and appInfo have different appName");
return false;
}
return true;
}
std::shared_ptr<BundleMgrHelper> AppPreloader::GetBundleManagerHelper()
{
if (!remoteClientManager_) {
TAG_LOGE(AAFwkTag::APPMGR, "null remoteClientManager_");
return nullptr;
}
return remoteClientManager_->GetBundleManagerHelper();
}
}
}