diff --git a/appexecfwk.gni b/appexecfwk.gni index 5d36e2dc..9584cd54 100644 --- a/appexecfwk.gni +++ b/appexecfwk.gni @@ -20,6 +20,7 @@ services_path = "${appexecfwk_path}/services" kits_path = "${appexecfwk_path}/kits" innerkits_path = "${appexecfwk_path}/interfaces/innerkits" tools_path = "${appexecfwk_path}/tools" +use_pre_bundle_profile = false declare_args() { bundle_framework_graphics = true bundle_framework_free_install = true diff --git a/interfaces/innerkits/appexecfwk_base/include/appexecfwk_errors.h b/interfaces/innerkits/appexecfwk_base/include/appexecfwk_errors.h index ee9f7d84..44bc8b6c 100644 --- a/interfaces/innerkits/appexecfwk_base/include/appexecfwk_errors.h +++ b/interfaces/innerkits/appexecfwk_base/include/appexecfwk_errors.h @@ -200,7 +200,9 @@ enum { ERR_APPEXECFWK_FORM_SEND_FMS_MSG, ERR_APPEXECFWK_FORM_FORM_DUPLICATE_ADDED, ERR_APPEXECFWK_FORM_IN_RECOVER, - ERR_APPEXECFWK_FORM_GET_SYSMGR_FAILED + ERR_APPEXECFWK_FORM_GET_SYSMGR_FAILED, + // error code in prebundle sacn + ERR_APPEXECFWK_PARSE_FILE_FAILED }; // Error code for Hidump constexpr ErrCode APPEXECFWK_HIDUMP = ErrCodeOffset(SUBSYS_APPEXECFWK, APPEXECFWK_MODULE_HIDUMP); diff --git a/interfaces/innerkits/appexecfwk_base/include/bundle_constants.h b/interfaces/innerkits/appexecfwk_base/include/bundle_constants.h index 11280ebf..48c1373a 100644 --- a/interfaces/innerkits/appexecfwk_base/include/bundle_constants.h +++ b/interfaces/innerkits/appexecfwk_base/include/bundle_constants.h @@ -224,6 +224,12 @@ constexpr std::string_view ABILTY_NAME = "abilityName"; const std::string HMDFS_CONFIG_PATH {"/config/hmdfs/"}; const std::string BUNDLE_ID_FILE = { "bid" }; const std::string PATH_SEPERATE {"/"}; + +// pre bundle profile +const std::string DEFAULT_PRE_BUNDLE_PROFILE = "/system/etc/bundle"; +const std::string PREINSTALL_CONFIG = "/preinstall_config.json"; +const std::string PREINSTALL_UNINSTALL_CONFIG = "/pre_uninstall_config.json"; +const std::string PREINSTALL_ABILITY_CONFIG = "/preinstall_ability_config.json"; } // namespace Constants } // namespace AppExecFwk } // namespace OHOS diff --git a/services/bundlemgr/BUILD.gn b/services/bundlemgr/BUILD.gn index b8130913..fabc6b3a 100644 --- a/services/bundlemgr/BUILD.gn +++ b/services/bundlemgr/BUILD.gn @@ -90,6 +90,7 @@ ohos_source_set("bundle_parser") { "src/bundle_parser.cpp", "src/bundle_profile.cpp", "src/module_profile.cpp", + "src/pre_bundle_profile.cpp", ] public_configs = bundlemgr_parser_common_config @@ -239,6 +240,10 @@ ohos_shared_library("libbms") { defines += [ "HICOLLIE_ENABLE" ] } + if (use_pre_bundle_profile) { + defines += [ "USE_PRE_BUNDLE_PROFILE" ] + } + subsystem_name = "appexecfwk" part_name = "bundle_framework" } diff --git a/services/bundlemgr/include/bundle_mgr_service_event_handler.h b/services/bundlemgr/include/bundle_mgr_service_event_handler.h index 5e8f829f..805c8f17 100644 --- a/services/bundlemgr/include/bundle_mgr_service_event_handler.h +++ b/services/bundlemgr/include/bundle_mgr_service_event_handler.h @@ -19,6 +19,7 @@ #include "bundle_constants.h" #include "bundle_data_mgr.h" #include "event_handler.h" +#include "pre_scan_info.h" namespace OHOS { namespace AppExecFwk { @@ -44,7 +45,38 @@ public: private: /** - * @brief Install system and system vendor bundles. + * @brief start boot scan. + * @param userId Indicates the userId. + * @return + */ + void OnBootStartScanning(int32_t userId = Constants::UNSPECIFIED_USERID); + /** + * @brief Process boot bundle install from scan. + * @param userId Indicates the userId. + * @return + */ + void ProcessBootBundleInstallFromScan(int32_t userId); + /** + * @brief Process boot bundle install from pre bundle profile. + * @param userId Indicates the userId. + * @return + */ + void ProcessBootBundleInstallFromPreBundleProFile(int32_t userId); + /** + * @brief Process bundle install by scanInfos. + * @param scanInfos Indicates the scanInfos contains installed info. + * @param uninstallBundleNames Indicates the uninstall bundleNames. + * @param preBundleConfigInfos Indicates the preBundleConfigInfos. + * @param userId Indicates the userId. + * @return + */ + void InnerProcessBootPreBundleProFileInstall( + const std::set &scanInfos, + const std::set &uninstallBundleNames, + const std::set &preBundleConfigInfos, + int32_t userId); + /** + * @brief Install bundles by scanDir. * @param scanDir Indicates the scanDir. * @param appType Indicates the bundle type. * @param userId Indicates userId. @@ -52,29 +84,114 @@ private: */ void ProcessSystemBundleInstall(const std::string &scanDir, Constants::AppType appType, int32_t userId = Constants::UNSPECIFIED_USERID); + /** + * @brief Install bundles by preScanInfo. + * @param preScanInfo Indicates the preScanInfo. + * @param preBundleConfig Indicates the preBundleConfig. + * @param userId Indicates userId. + * @return + */ + void ProcessSystemBundleInstall( + const PreScanInfo &preScanInfo, + const PreBundleConfigInfo &preBundleConfig, + int32_t userId); + /** + * @brief start reboot scan. + * @param userId Indicates the userId. + * @return + */ + void OnRebootStartScanning(int32_t userId = Constants::UNSPECIFIED_USERID); + /** + * @brief Process reboot bundle. + * @param userId Indicates the userId. + * @return + */ + void ProcessRebootBundle(int32_t userId); + /** + * @brief Obtains the PreInstallBundleInfo objects. + * @return Returns true if this function is successfully called; returns false otherwise. + */ + bool LoadAllPreInstallBundleInfos(); + /** + * @brief Process reboot bundle install. + * @return + */ + void ProcessRebootBundleInstall(); + /** + * @brief Process reboot bundle install from pre bundle profile. + * @return + */ + void ProcessRebootBundleInstallFromPreBundleProFile(); + /** + * @brief Process reboot bundle install by scanInfos. + * @param scanInfos Indicates the scanInfos contains installed info. + * @param uninstallBundleNames Indicates the uninstall bundleNames. + * @param preBundleConfigInfos Indicates the preBundleConfigInfos. + * @return + */ + void ProcessReBootPreBundleProFileInstall( + const std::set &scanInfos, + const std::set &uninstallBundleNames, + const std::set &preBundleConfigInfos); + /** + * @brief Process reboot bundle install from scan. + * @return + */ + void ProcessRebootBundleInstallFromScan(); + /** + * @brief Process reboot install bundles by bundleList. + * @param bundleList Indicates store bundle list. + * @param appType Indicates the bundle type. + * @return + */ + void InnerProcessRebootBundleInstall( + const std::list &bundleList, Constants::AppType appType); + /** + * @brief Reboot uninstall system and system vendor bundles. + * @return + */ + void ProcessRebootBundleUninstall(); + /** + * @brief Get bundle dir by scan. + * @param bundleDirs Indicates the return bundleDirs. + * @return + */ + void GetBundleDirFromScan(std::list &bundleDirs); + /** + * @brief Process scan dir. + * @param dir Indicates the dir. + * @param bundleDirs Indicates the return bundleDirs. + * @return + */ + void ProcessScanDir(const std::string &dir, std::list &bundleDirs); + /** + * @brief Get bundle dir by pre bundle profile. + * @param scanInfos Indicates the scanInfos contains installed info. + * @param uninstallBundleNames Indicates the uninstall bundleNames. + * @param preBundleConfigInfos Indicates the preBundleConfigInfos. + * @return + */ + void GetBundleDirFromPreBundleProFile( + std::set &scanInfos, + std::set &uninstallBundleNames, + std::set &preBundleConfigInfos); + /** + * @brief Process parse pre bundle profile. + * @param scanInfos Indicates the scanInfos contains installed info. + * @param uninstallBundleNames Indicates the uninstall bundleNames. + * @param preBundleConfigInfos Indicates the preBundleConfigInfos. + * @return + */ + void ParsePreBundleProFile( + std::string dir, + std::set &scanInfos, + std::set &uninstallBundleNames, + std::set &preBundleConfigInfos); /** * @brief Set the flag indicates that all system and vendor applications installed. * @return */ void SetAllInstallFlag() const; - /** - * @brief start scan. - * @param userId Indicates the userId. - * @return - */ - void OnStartScanning(int32_t userId = Constants::UNSPECIFIED_USERID); - /** - * @brief start scan. - * @param userId Indicates the userId. - * @return - */ - void RebootStartScanning(int32_t userId = Constants::UNSPECIFIED_USERID); - /** - * @brief Install system and system vendor bundles. - * @param userId Indicates userId. - * @return - */ - void RebootProcessSystemBundle(int32_t userId = Constants::UNSPECIFIED_USERID); /** * @brief Get bundleinfo of HAP by path. * @param hapFilePath Indicates the absolute file path of the HAP. @@ -83,19 +200,6 @@ private: */ bool ParseHapFiles(const std::string &hapFilePath, std::unordered_map &infos); - /** - * @brief Reboot install system and system vendor bundles. - * @param bundleList Indicates store bundle list. - * @param appType Indicates the bundle type. - * @return - */ - void RebootBundleInstall( - const std::list &bundleList, Constants::AppType appType); - /** - * @brief Reboot uninstall system and system vendor bundles. - * @return - */ - void RebootBundleUninstall(); /** * @brief To check the version code and bundleName in all haps. * @param infos .Indicates all innerBundleInfo for all haps need to be installed. @@ -132,26 +236,11 @@ private: */ void AddParseInfosToMap(const std::string &bundleName, const std::unordered_map &infos); - /** - * @brief Obtains the PreInstallBundleInfo objects. - * @return Returns true if this function is successfully called; returns false otherwise. - */ - bool LoadAllPreInstallBundleInfos(); - /** - * @brief Reboot Install system and system vendor bundles. - * @param scanDir Indicates the scanDir. - * @param appType Indicates the bundle type. - * @return - */ - void RebootProcessBundleInstall( - const std::string &scanDir, Constants::AppType appType); // Used to save the information parsed by Hap in the scanned directory. std::map> hapParseInfoMap_; // used to save application information that already exists in the Db. std::map loadExistData_; - - std::vector scanPaths_; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/bundlemgr/include/bundle_parser.h b/services/bundlemgr/include/bundle_parser.h index b4c1e882..e410640e 100644 --- a/services/bundlemgr/include/bundle_parser.h +++ b/services/bundlemgr/include/bundle_parser.h @@ -16,10 +16,12 @@ #ifndef FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_BUNDLE_PARSER_H #define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_BUNDLE_PARSER_H +#include #include #include "appexecfwk_errors.h" #include "inner_bundle_info.h" +#include "pre_scan_info.h" namespace OHOS { namespace AppExecFwk { @@ -41,6 +43,30 @@ public: * @return Returns ERR_OK if the bundle successfully parsed; returns ErrCode otherwise. */ ErrCode ParseSysCap(const std::string &pathName, std::vector &sysCaps) const; + /** + * @brief Parse scanInfos by the configFile. + * @param configFile Indicates the path of configFile. + * @param scanInfos Indicates the obtained InnerBundleInfo object. + * @return Returns ERR_OK if the bundle successfully parsed; returns ErrCode otherwise. + */ + ErrCode ParsePreInstallConfig( + const std::string &configFile, std::set &scanInfos) const; + /** + * @brief Parse bundleNames by the configFile. + * @param configFile Indicates the path of configFile. + * @param bundleNames Indicates the bundleNames. + * @return Returns ERR_OK if the bundle successfully parsed; returns ErrCode otherwise. + */ + ErrCode ParsePreUnInstallConfig( + const std::string &configFile, std::set &bundleNames) const; + /** + * @brief Parse PreBundleConfigInfo by the configFile. + * @param configFile Indicates the path of configFile. + * @param preBundleConfigInfos Indicates the obtained preBundleConfigInfo object. + * @return Returns ERR_OK if the bundle successfully parsed; returns ErrCode otherwise. + */ + ErrCode ParsePreInstallAbilityConfig( + const std::string &configFile, std::set &preBundleConfigInfos) const; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/bundlemgr/include/pre_bundle_profile.h b/services/bundlemgr/include/pre_bundle_profile.h new file mode 100644 index 00000000..620c7020 --- /dev/null +++ b/services/bundlemgr/include/pre_bundle_profile.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#ifndef FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_BUNDLE_PROFILE_H +#define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_BUNDLE_PROFILE_H + +#include + +#include "appexecfwk_errors.h" +#include "json_util.h" +#include "pre_scan_info.h" + +namespace OHOS { +namespace AppExecFwk { +class PreBundleProfile { +public: + /** + * @brief Transform the jsonBuf to scanInfos. + * @param jsonBuf Indicates the jsonBuf. + * @param scanInfos Indicates the scanInfos. + * @return Returns ERR_OK if the information transformed successfully; returns error code otherwise. + */ + ErrCode TransformTo( + const nlohmann::json &jsonBuf, std::set &scanInfos) const; + /** + * @brief Transform the jsonBuf to bundleNames. + * @param jsonBuf Indicates the jsonBuf. + * @param bundleNames Indicates the bundleNames. + * @return Returns ERR_OK if the information transformed successfully; returns error code otherwise. + */ + ErrCode TransformTo( + const nlohmann::json &jsonBuf, std::set &bundleNames) const; + /** + * @brief Transform the jsonBuf to preBundleConfigInfos. + * @param jsonBuf Indicates the jsonBuf. + * @param preBundleConfigInfos Indicates the preBundleConfigInfos. + * @return Returns ERR_OK if the information transformed successfully; returns error code otherwise. + */ + ErrCode TransformTo( + const nlohmann::json &jsonBuf, std::set &preBundleConfigInfos) const; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_BUNDLE_PROFILE_H diff --git a/services/bundlemgr/include/pre_scan_info.h b/services/bundlemgr/include/pre_scan_info.h new file mode 100644 index 00000000..90385722 --- /dev/null +++ b/services/bundlemgr/include/pre_scan_info.h @@ -0,0 +1,105 @@ +/* + * 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. + */ + +#ifndef FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_SCAN_INFO_H +#define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_SCAN_INFO_H + +#include + +namespace OHOS { +namespace AppExecFwk { +namespace { + std::string GetBoolStrVal(bool val) + { + return val ? "true" : "false"; + } +} +struct PreBundleConfigInfo { + std::string bundleName; + bool systemapi = false; + bool keepAlive = false; + bool singleton = false; + bool userDataClearable = false; + bool multiProcess = false; + bool bootable = false; + bool notification = false; + bool hideDesktopIcon = false; + bool queryPriority = false; + bool startStaticBroadcast = false; + bool startGuiAbilityBackground = false; + + bool operator <(const PreBundleConfigInfo &preBundleConfigInfo) const + { + return bundleName < preBundleConfigInfo.bundleName; + } + + void Reset() + { + bundleName.clear(); + systemapi = false; + keepAlive = false; + singleton = false; + userDataClearable = false; + multiProcess = false; + bootable = false; + notification = false; + hideDesktopIcon = false; + queryPriority = false; + startStaticBroadcast = false; + startGuiAbilityBackground = false; + } + + std::string ToString() + { + return "[ bundleName = " + bundleName + ", systemapi = " + GetBoolStrVal(systemapi) + + ", singleton = " + GetBoolStrVal(singleton) + "]"; + } +}; + +struct PreScanInfo { + std::string bundleDir; + bool removable = false; + int32_t priority = 0; + + bool operator < (const PreScanInfo &preScanInfo) const + { + if (bundleDir == preScanInfo.bundleDir) { + return false; + } + + return priority >= preScanInfo.priority; + } + + friend bool operator == (const PreScanInfo& oldPreScanInfo, const PreScanInfo& newPreScanInfo) + { + return oldPreScanInfo.bundleDir == newPreScanInfo.bundleDir; + } + + void Reset() + { + bundleDir.clear(); + removable = false; + priority = 0; + } + + std::string ToString() + { + return "[ bundleDir = " + bundleDir + ", removable = " + GetBoolStrVal(removable) + + ", priority = " + std::to_string(priority) + "]"; + } +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_PRE_SCAN_INFO_H diff --git a/services/bundlemgr/src/bundle_mgr_service_event_handler.cpp b/services/bundlemgr/src/bundle_mgr_service_event_handler.cpp index 2ae66bed..fd01c9ab 100644 --- a/services/bundlemgr/src/bundle_mgr_service_event_handler.cpp +++ b/services/bundlemgr/src/bundle_mgr_service_event_handler.cpp @@ -19,6 +19,7 @@ #include "app_log_wrapper.h" #include "bundle_mgr_service.h" +#include "bundle_parser.h" #include "bundle_scanner.h" #ifdef CONFIG_POLOCY_ENABLE #include "config_policy_utils.h" @@ -30,6 +31,17 @@ namespace OHOS { namespace AppExecFwk { namespace { const std::string APP_SUFFIX = "/app"; +const std::string PRODUCT_SUFFIX = "/etc/bundle"; + +std::string GetScanBundleName(const std::string &str) +{ + auto index = str.find_last_of('/'); + if (index != std::string::npos) { + return str.substr(index + 1); + } + + return ""; +} } BMSEventHandler::BMSEventHandler(const std::shared_ptr &runner) : EventHandler(runner) { @@ -45,7 +57,7 @@ void BMSEventHandler::ProcessEvent(const InnerEvent::Pointer &event) { switch (event->GetInnerEventId()) { case BUNDLE_SCAN_START: { - OnStartScanning(Constants::DEFAULT_USERID); + OnBootStartScanning(Constants::DEFAULT_USERID); SetAllInstallFlag(); DelayedSingleton::GetInstance()->RegisterService(); break; @@ -55,7 +67,7 @@ void BMSEventHandler::ProcessEvent(const InnerEvent::Pointer &event) case BMS_START_FINISHED: break; case BUNDLE_REBOOT_SCAN_START: { - RebootStartScanning(); + OnRebootStartScanning(); SetAllInstallFlag(); DelayedSingleton::GetInstance()->RegisterService(); break; @@ -66,13 +78,30 @@ void BMSEventHandler::ProcessEvent(const InnerEvent::Pointer &event) } } -void BMSEventHandler::OnStartScanning(int32_t userId) +void BMSEventHandler::OnBootStartScanning(int32_t userId) { - scanPaths_.clear(); - ProcessSystemBundleInstall( - Constants::SYSTEM_APP_SCAN_PATH, Constants::AppType::SYSTEM_APP, userId); - ProcessSystemBundleInstall( - Constants::THIRD_SYSTEM_APP_SCAN_PATH, Constants::AppType::THIRD_SYSTEM_APP, userId); +#ifdef USE_PRE_BUNDLE_PROFILE + ProcessBootBundleInstallFromPreBundleProFile(userId); +#else + ProcessBootBundleInstallFromScan(userId); +#endif + PerfProfile::GetInstance().Dump(); +} + +void BMSEventHandler::ProcessBootBundleInstallFromScan(int32_t userId) +{ + APP_LOGD("Process boot bundle install from scan"); + std::list bundleDirs; + GetBundleDirFromScan(bundleDirs); + for (auto item : bundleDirs) { + ProcessSystemBundleInstall(item, Constants::AppType::SYSTEM_APP, userId); + } +} + +void BMSEventHandler::GetBundleDirFromScan(std::list &bundleDirs) +{ + ProcessScanDir(Constants::SYSTEM_APP_SCAN_PATH, bundleDirs); + ProcessScanDir(Constants::THIRD_SYSTEM_APP_SCAN_PATH, bundleDirs); #ifdef CONFIG_POLOCY_ENABLE auto cfgDirList = GetCfgDirList(); if (cfgDirList == nullptr) { @@ -86,46 +115,140 @@ void BMSEventHandler::OnStartScanning(int32_t userId) } APP_LOGD("cfgDir: %{public}s ", cfgDir); - ProcessSystemBundleInstall( - cfgDir + APP_SUFFIX, Constants::AppType::SYSTEM_APP, userId); + ProcessScanDir(cfgDir + APP_SUFFIX, bundleDirs); } #endif + auto iter = std::find(bundleDirs.begin(), bundleDirs.end(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); + if (iter != bundleDirs.end()) { + bundleDirs.erase(iter); + bundleDirs.insert(bundleDirs.begin(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); + } else { + iter = std::find(bundleDirs.begin(), bundleDirs.end(), Constants::SYSTEM_RESOURCES_APP_PATH); + if (iter != bundleDirs.end()) { + bundleDirs.erase(iter); + bundleDirs.insert(bundleDirs.begin(), Constants::SYSTEM_RESOURCES_APP_PATH); + } + } } -void BMSEventHandler::ProcessSystemBundleInstall( - const std::string &scanDir, Constants::AppType appType, int32_t userId) +void BMSEventHandler::ProcessScanDir(const std::string &dir, std::list &bundleDirs) { - APP_LOGD("scan thread start"); - if (std::find(scanPaths_.begin(), scanPaths_.end(), scanDir) != scanPaths_.end()) { - APP_LOGD("scanDir(%{public}s) has scan", scanDir.c_str()); + BundleScanner scanner; + std::list bundleList = scanner.Scan(dir); + for (auto item : bundleList) { + auto iter = std::find(bundleDirs.begin(), bundleDirs.end(), item); + if (iter == bundleDirs.end()) { + bundleDirs.push_back(item); + } + } +} + +void BMSEventHandler::ProcessBootBundleInstallFromPreBundleProFile(int32_t userId) +{ + APP_LOGD("Process boot bundle install from pre bundle proFile"); + std::set scanInfos; + std::set uninstallBundleNames; + std::set preBundleConfigInfos; + GetBundleDirFromPreBundleProFile(scanInfos, uninstallBundleNames, preBundleConfigInfos); + InnerProcessBootPreBundleProFileInstall(scanInfos, uninstallBundleNames, preBundleConfigInfos, userId); +} + +void BMSEventHandler::GetBundleDirFromPreBundleProFile( + std::set &scanInfos, + std::set &uninstallBundleNames, + std::set &preBundleConfigInfos) +{ + std::set preBundleProFileDirs; + // Product catalog +#ifdef CONFIG_POLOCY_ENABLE + auto cfgDirList = GetCfgDirList(); + if (cfgDirList == nullptr) { + APP_LOGD("cfgDirList is empty"); return; } - APP_LOGD("scanDir: %{public}s and userId: %{public}d", scanDir.c_str(), userId); - scanPaths_.emplace_back(scanDir); - auto scanner = std::make_unique(); - std::list bundleList = scanner->Scan(scanDir); - auto iter = std::find(bundleList.begin(), bundleList.end(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); - if (iter != bundleList.end()) { - bundleList.erase(iter); - bundleList.insert(bundleList.begin(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); - } else { - iter = std::find(bundleList.begin(), bundleList.end(), Constants::SYSTEM_RESOURCES_APP_PATH); - if (iter != bundleList.end()) { - bundleList.erase(iter); - bundleList.insert(bundleList.begin(), Constants::SYSTEM_RESOURCES_APP_PATH); + for (auto cfgDir : cfgDirList->paths) { + if (!cfgDir) { + continue; } - } - for (const auto &item : bundleList) { - SystemBundleInstaller installer; - APP_LOGD("scan item %{public}s", item.c_str()); - if (!installer.InstallSystemBundle(item, appType, userId)) { - APP_LOGW("Install System app:%{public}s error", item.c_str()); + std::string preBundleProFileDir = cfgDir + PRODUCT_SUFFIX; + APP_LOGD("preBundleProFileDir: %{public}s ", preBundleProFileDir.c_str()); + if (preBundleProFileDirs.find(preBundleProFileDir) != preBundleProFileDirs.end()) { + APP_LOGE("preBundleProFileDir(%{public}s) has parsed", preBundleProFileDir.c_str()); + continue; } - } - PerfProfile::GetInstance().Dump(); + preBundleProFileDirs.insert(preBundleProFileDir); + ParsePreBundleProFile(preBundleProFileDir, scanInfos, uninstallBundleNames, preBundleConfigInfos); + } +#endif + // Default catalog + if (preBundleProFileDirs.find(Constants::DEFAULT_PRE_BUNDLE_PROFILE) == preBundleProFileDirs.end()) { + ParsePreBundleProFile( + Constants::DEFAULT_PRE_BUNDLE_PROFILE, scanInfos, uninstallBundleNames, preBundleConfigInfos); + } +} + +void BMSEventHandler::ParsePreBundleProFile( + std::string dir, + std::set &scanInfos, + std::set &uninstallBundleNames, + std::set &preBundleConfigInfos) +{ + BundleParser bundleParser; + bundleParser.ParsePreInstallConfig( + dir + Constants::PREINSTALL_CONFIG, scanInfos); + bundleParser.ParsePreUnInstallConfig( + dir + Constants::PREINSTALL_UNINSTALL_CONFIG, uninstallBundleNames); + bundleParser.ParsePreInstallAbilityConfig( + dir + Constants::PREINSTALL_ABILITY_CONFIG, preBundleConfigInfos); +} + +void BMSEventHandler::InnerProcessBootPreBundleProFileInstall( + const std::set &scanInfos, + const std::set &uninstallBundleNames, + const std::set &preBundleConfigInfos, + int32_t userId) +{ + for (auto scanInfo : scanInfos) { + APP_LOGD("Inner process boot preBundle proFile install %{public}s", scanInfo.ToString().c_str()); + std::string scanBundleName = GetScanBundleName(scanInfo.bundleDir); + if (uninstallBundleNames.find(scanBundleName) != uninstallBundleNames.end()) { + APP_LOGW("bundle(%{public}s) not allowed installed", scanBundleName.c_str()); + continue; + } + + PreBundleConfigInfo preBundleConfigInfo; + preBundleConfigInfo.bundleName = scanBundleName; + auto iter = preBundleConfigInfos.find(preBundleConfigInfo); + if (iter != preBundleConfigInfos.end()) { + preBundleConfigInfo = *iter; + } + + ProcessSystemBundleInstall(scanInfo, preBundleConfigInfo, userId); + } +} + +void BMSEventHandler::ProcessSystemBundleInstall( + const PreScanInfo &preScanInfo, const PreBundleConfigInfo &preBundleConfig, int32_t userId) +{ + APP_LOGD("Process system bundle install by preScanInfo(%{public}s)", preScanInfo.bundleDir.c_str()); + SystemBundleInstaller installer; + if (!installer.InstallSystemBundle( + preScanInfo.bundleDir, Constants::AppType::SYSTEM_APP, userId)) { + APP_LOGW("Install System app:%{public}s error", preScanInfo.bundleDir.c_str()); + } +} + +void BMSEventHandler::ProcessSystemBundleInstall( + const std::string &bundleDir, Constants::AppType appType, int32_t userId) +{ + APP_LOGD("Process system bundle install by bundleDir(%{public}s)", bundleDir.c_str()); + SystemBundleInstaller installer; + if (!installer.InstallSystemBundle(bundleDir, appType, userId)) { + APP_LOGW("Install System app:%{public}s error", bundleDir.c_str()); + } } void BMSEventHandler::SetAllInstallFlag() const @@ -139,45 +262,21 @@ void BMSEventHandler::SetAllInstallFlag() const dataMgr->SetInitialUserFlag(true); } -void BMSEventHandler::RebootStartScanning(int32_t userId) +void BMSEventHandler::OnRebootStartScanning(int32_t userId) { - scanPaths_.clear(); - auto future = std::async(std::launch::async, [this, userId] { - RebootProcessSystemBundle(userId); - }); - future.get(); + ProcessRebootBundle(userId); } -void BMSEventHandler::RebootProcessSystemBundle(int32_t userId) +void BMSEventHandler::ProcessRebootBundle(int32_t userId) { - APP_LOGD("reboot scan thread start"); + APP_LOGD("Process reboot bundle start"); if (!LoadAllPreInstallBundleInfos()) { APP_LOGE("Load all preInstall bundleInfos failed."); return; } - RebootProcessBundleInstall( - Constants::SYSTEM_APP_SCAN_PATH, Constants::AppType::SYSTEM_APP); - RebootProcessBundleInstall( - Constants::THIRD_SYSTEM_APP_SCAN_PATH, Constants::AppType::THIRD_SYSTEM_APP); -#ifdef CONFIG_POLOCY_ENABLE - auto cfgDirList = GetCfgDirList(); - if (cfgDirList == nullptr) { - APP_LOGD("cfgDirList is empty"); - return; - } - - for (auto cfgDir : cfgDirList->paths) { - if (!cfgDir) { - continue; - } - - APP_LOGD("cfgDir: %{public}s ", cfgDir); - RebootProcessBundleInstall(cfgDir + APP_SUFFIX, Constants::AppType::SYSTEM_APP); - } -#endif - - RebootBundleUninstall(); + ProcessRebootBundleInstall(); + ProcessRebootBundleUninstall(); } bool BMSEventHandler::LoadAllPreInstallBundleInfos() @@ -197,34 +296,55 @@ bool BMSEventHandler::LoadAllPreInstallBundleInfos() return true; } -void BMSEventHandler::RebootProcessBundleInstall( - const std::string &scanDir, Constants::AppType appType) +void BMSEventHandler::ProcessRebootBundleInstall() { - if (std::find(scanPaths_.begin(), scanPaths_.end(), scanDir) != scanPaths_.end()) { - APP_LOGD("Reboot scanDir(%{public}s) has scan", scanDir.c_str()); - return; - } - - APP_LOGD("Reboot scanDir: %{public}s", scanDir.c_str()); - scanPaths_.emplace_back(scanDir); - auto scanner = std::make_unique(); - std::list bundleList = scanner->Scan(scanDir); - auto iter = std::find(bundleList.begin(), bundleList.end(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); - if (iter != bundleList.end()) { - bundleList.erase(iter); - bundleList.insert(bundleList.begin(), Constants::SYSTEM_RESOURCES_APP_PATH_NEW); - } else { - iter = std::find(bundleList.begin(), bundleList.end(), Constants::SYSTEM_RESOURCES_APP_PATH); - if (iter != bundleList.end()) { - bundleList.erase(iter); - bundleList.insert(bundleList.begin(), Constants::SYSTEM_RESOURCES_APP_PATH); - } - } - - RebootBundleInstall(bundleList, appType); + APP_LOGD("Process reboot bundle install start"); +#ifdef USE_PRE_BUNDLE_PROFILE + ProcessRebootBundleInstallFromPreBundleProFile(); +#else + ProcessRebootBundleInstallFromScan(); +#endif } -void BMSEventHandler::RebootBundleInstall( +void BMSEventHandler::ProcessRebootBundleInstallFromPreBundleProFile() +{ + APP_LOGD("Process reboot bundle install from pre bundle proFile"); + std::set scanInfos; + std::set uninstallBundleNames; + std::set preBundleConfigInfos; + GetBundleDirFromPreBundleProFile(scanInfos, uninstallBundleNames, preBundleConfigInfos); + ProcessReBootPreBundleProFileInstall(scanInfos, uninstallBundleNames, preBundleConfigInfos); +} + +void BMSEventHandler::ProcessReBootPreBundleProFileInstall( + const std::set &scanInfos, + const std::set &uninstallBundleNames, + const std::set &preBundleConfigInfos) +{ + std::list bundleDirs; + for (auto scanInfo : scanInfos) { + APP_LOGD("Process reboot preBundle proFile install %{public}s", scanInfo.ToString().c_str()); + std::string scanBundleName = GetScanBundleName(scanInfo.bundleDir); + if (uninstallBundleNames.find(scanBundleName) != uninstallBundleNames.end()) { + APP_LOGW("bundle(%{public}s) not allowed installed", scanBundleName.c_str()); + continue; + } + + bundleDirs.push_back(scanInfo.bundleDir); + } + + InnerProcessRebootBundleInstall(bundleDirs, Constants::AppType::SYSTEM_APP); +} + +void BMSEventHandler::ProcessRebootBundleInstallFromScan() +{ + APP_LOGD("Process reboot bundle install from scan"); + std::list bundleDirs; + GetBundleDirFromScan(bundleDirs); + InnerProcessRebootBundleInstall(bundleDirs, Constants::AppType::SYSTEM_APP); +} + +void BMSEventHandler::InnerProcessRebootBundleInstall( const std::list &scanPathList, Constants::AppType appType) { auto dataMgr = DelayedSingleton::GetInstance()->GetDataMgr(); @@ -234,10 +354,10 @@ void BMSEventHandler::RebootBundleInstall( } for (auto &scanPathIter : scanPathList) { - APP_LOGD("reboot scan bundle path: %{private}s ", scanPathIter.c_str()); + APP_LOGD("reboot scan bundle path: %{public}s ", scanPathIter.c_str()); std::unordered_map infos; if (!ParseHapFiles(scanPathIter, infos) || infos.empty()) { - APP_LOGE("obtain bundleinfo failed : %{private}s ", scanPathIter.c_str()); + APP_LOGE("obtain bundleinfo failed : %{public}s ", scanPathIter.c_str()); continue; } @@ -335,7 +455,7 @@ void BMSEventHandler::AddParseInfosToMap( hapParseInfoMap_.at(bundleName) = iterMap; } -void BMSEventHandler::RebootBundleUninstall() +void BMSEventHandler::ProcessRebootBundleUninstall() { APP_LOGD("Reboot scan and OTA uninstall start"); auto dataMgr = DelayedSingleton::GetInstance()->GetDataMgr(); diff --git a/services/bundlemgr/src/bundle_parser.cpp b/services/bundlemgr/src/bundle_parser.cpp index f2a9679b..fbd35098 100644 --- a/services/bundlemgr/src/bundle_parser.cpp +++ b/services/bundlemgr/src/bundle_parser.cpp @@ -15,19 +15,24 @@ #include "bundle_parser.h" +#include #include +#include #include "app_log_wrapper.h" #include "bundle_constants.h" #include "bundle_extractor.h" #include "bundle_profile.h" #include "module_profile.h" +#include "pre_bundle_profile.h" #include "rpcid_decode/syscap_tool.h" #include "securec.h" namespace OHOS { namespace AppExecFwk { namespace { +const std::string INSTALL_ABILITY_CONFIGS = "install_ability_configs"; + bool ParseStr(const char *buf, const int itemLen, int totalLen, std::vector &sysCaps) { APP_LOGD("Parse rpcid output start, itemLen:%{public}d totalLen:%{public}d.", itemLen, totalLen); @@ -50,6 +55,42 @@ bool ParseStr(const char *buf, const int itemLen, int totalLen, std::vector &scanInfos) const +{ + APP_LOGD("Parse preInstallConfig from %{public}s", configFile.c_str()); + nlohmann::json jsonBuf; + if (!ReadFileIntoJson(configFile, jsonBuf)) { + APP_LOGE("Parse preInstallConfig file failed"); + return ERR_APPEXECFWK_PARSE_FILE_FAILED; + } + + PreBundleProfile preBundleProfile; + return preBundleProfile.TransformTo(jsonBuf, scanInfos); +} + +ErrCode BundleParser::ParsePreUnInstallConfig( + const std::string &configFile, std::set &bundleNames) const +{ + APP_LOGD("Parse PreUnInstallConfig from %{public}s", configFile.c_str()); + nlohmann::json jsonBuf; + if (!ReadFileIntoJson(configFile, jsonBuf)) { + APP_LOGE("Parse preUnInstallConfig file failed"); + return ERR_APPEXECFWK_PARSE_FILE_FAILED; + } + + PreBundleProfile preBundleProfile; + return preBundleProfile.TransformTo(jsonBuf, bundleNames); +} + +ErrCode BundleParser::ParsePreInstallAbilityConfig( + const std::string &configFile, std::set &preBundleConfigInfos) const +{ + APP_LOGD("Parse PreInstallAbilityConfig from %{public}s", configFile.c_str()); + nlohmann::json jsonBuf; + if (!ReadFileIntoJson(configFile, jsonBuf)) { + APP_LOGE("Parse preInstallAbilityConfig file failed"); + return ERR_APPEXECFWK_PARSE_FILE_FAILED; + } + + PreBundleProfile preBundleProfile; + return preBundleProfile.TransformTo(jsonBuf, preBundleConfigInfos); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/bundlemgr/src/pre_bundle_profile.cpp b/services/bundlemgr/src/pre_bundle_profile.cpp new file mode 100644 index 00000000..27a7c664 --- /dev/null +++ b/services/bundlemgr/src/pre_bundle_profile.cpp @@ -0,0 +1,287 @@ +/* + * 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 "pre_bundle_profile.h" + +#include "app_log_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +const std::string INSTALL_LIST = "install_list"; +const std::string UNINSTALL_LIST = "uninstall_list"; +const std::string INSTALL_ABILITY_CONFIGS = "install_ability_configs"; +const std::string BUNDLE_DIR = "bundle_dir"; +const std::string REMOVABLE = "removable"; +const std::string PRIORITY = "priority"; +const std::string BUNDLE_NAME = "bundleName"; +const std::string SYSTEMAPI = "systemapi"; +const std::string KEEP_ALIVE = "keepAlive"; +const std::string SINGLETON = "singleton"; +const std::string USER_DATA_CLEARABLE = "userDataClearable"; +const std::string MULTI_PROCESS = "multiProcess"; +const std::string BOOTABLE = "bootable"; +const std::string NOTIFICATION = "notification"; +const std::string HIDE_DESKTOP_ICON = "hideDesktopIcon"; +const std::string QUERY_PRIORITY = "queryPriority"; +const std::string START_STATIC_BROADCAST = "startStaticBroadcast"; +const std::string START_GUI_ABLITY_BACKGROUND = "startGuiAbilityBackground"; +} + +ErrCode PreBundleProfile::TransformTo( + const nlohmann::json &jsonBuf, std::set &scanInfos) const +{ + APP_LOGI("transform jsonBuf to PreScanInfos"); + if (jsonBuf.is_discarded()) { + APP_LOGE("profile format error"); + return ERR_APPEXECFWK_PARSE_BAD_PROFILE; + } + + if (jsonBuf.find(INSTALL_LIST) == jsonBuf.end()) { + return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR; + } + + auto arrays = jsonBuf.at(INSTALL_LIST); + if (!arrays.is_array() || arrays.empty()) { + APP_LOGE("value is not array"); + return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR; + } + + PreScanInfo preScanInfo; + for (const auto &array : arrays) { + if (!array.is_object()) { + APP_LOGE("array is not json object"); + return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR; + } + + preScanInfo.Reset(); + const auto &jsonObjectEnd = array.end(); + int32_t parseResult = ERR_OK; + GetValueIfFindKey(array, + jsonObjectEnd, + BUNDLE_DIR, + preScanInfo.bundleDir, + JsonType::STRING, + true, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + REMOVABLE, + preScanInfo.removable, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + PRIORITY, + preScanInfo.priority, + JsonType::NUMBER, + false, + parseResult, + ArrayType::NOT_ARRAY); + if (parseResult == ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP) { + APP_LOGE("bundleDir must exist, and it is empty here"); + continue; + } + + if (parseResult != ERR_OK) { + APP_LOGE("parse from json failed"); + return parseResult; + } + + if (std::find(scanInfos.begin(), scanInfos.end(), preScanInfo) != scanInfos.end()) { + APP_LOGE("preScanInfo(%{public}s) has exit", preScanInfo.ToString().c_str()); + continue; + } + + scanInfos.insert(preScanInfo); + } + + return ERR_OK; +} + +ErrCode PreBundleProfile::TransformTo( + const nlohmann::json &jsonBuf, std::set &bundleNames) const +{ + APP_LOGD("transform jsonBuf to bundleNames"); + if (jsonBuf.is_discarded()) { + APP_LOGE("profile format error"); + return ERR_APPEXECFWK_PARSE_BAD_PROFILE; + } + + const auto &jsonObjectEnd = jsonBuf.end(); + int32_t parseResult = ERR_OK; + std::vector names; + GetValueIfFindKey>(jsonBuf, + jsonObjectEnd, + UNINSTALL_LIST, + names, + JsonType::ARRAY, + false, + parseResult, + ArrayType::STRING); + for (auto name : names) { + APP_LOGD("bundleNames %{public}s", name.c_str()); + bundleNames.insert(name); + } + + return parseResult; +} + +ErrCode PreBundleProfile::TransformTo( + const nlohmann::json &jsonBuf, std::set &preBundleConfigInfos) const +{ + APP_LOGI("transform jsonBuf to preBundleConfigInfos"); + if (jsonBuf.is_discarded()) { + APP_LOGE("profile format error"); + return ERR_APPEXECFWK_PARSE_BAD_PROFILE; + } + + if (!jsonBuf.is_array() || jsonBuf.empty()) { + APP_LOGE("value is not array"); + return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR; + } + + PreBundleConfigInfo preBundleConfigInfo; + for (const auto &array : jsonBuf) { + if (!array.is_object()) { + APP_LOGE("array is not json object"); + return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR; + } + + preBundleConfigInfo.Reset(); + const auto &jsonObjectEnd = array.end(); + int32_t parseResult = ERR_OK; + GetValueIfFindKey(array, + jsonObjectEnd, + BUNDLE_NAME, + preBundleConfigInfo.bundleName, + JsonType::STRING, + true, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + SYSTEMAPI, + preBundleConfigInfo.systemapi, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + KEEP_ALIVE, + preBundleConfigInfo.keepAlive, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + SINGLETON, + preBundleConfigInfo.singleton, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + USER_DATA_CLEARABLE, + preBundleConfigInfo.userDataClearable, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + MULTI_PROCESS, + preBundleConfigInfo.multiProcess, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + BOOTABLE, + preBundleConfigInfo.bootable, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + NOTIFICATION, + preBundleConfigInfo.notification, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + HIDE_DESKTOP_ICON, + preBundleConfigInfo.hideDesktopIcon, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + QUERY_PRIORITY, + preBundleConfigInfo.queryPriority, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + START_STATIC_BROADCAST, + preBundleConfigInfo.startStaticBroadcast, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + GetValueIfFindKey(array, + jsonObjectEnd, + START_GUI_ABLITY_BACKGROUND, + preBundleConfigInfo.startGuiAbilityBackground, + JsonType::BOOLEAN, + false, + parseResult, + ArrayType::NOT_ARRAY); + if (parseResult == ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP) { + APP_LOGE("bundlename must exist, and it is empty here"); + continue; + } + + if (parseResult != ERR_OK) { + APP_LOGE("parse from json failed"); + return parseResult; + } + + if (preBundleConfigInfos.find(preBundleConfigInfo) != preBundleConfigInfos.end()) { + APP_LOGE("preBundleConfigInfo(%{public}s) has exit", preBundleConfigInfo.ToString().c_str()); + continue; + } + + preBundleConfigInfos.insert(preBundleConfigInfo); + } + + return ERR_OK; +} +} // namespace AppExecFwk +} // namespace OHOS