diff --git a/README_zh.md b/README_zh.md index 8d40656eb7421c3297af1f3069ce6cb09a579a7b..dc538324cda7243fb81b4eb67beb0986351d2eaa 100644 --- a/README_zh.md +++ b/README_zh.md @@ -22,6 +22,8 @@ foundation/bundlemanager/bundle_tool | help | 帮助命令,显示bm支持的命令信息。 | | install | 安装命令,用来安装应用。 | | uninstall | 卸载命令,用来卸载应用。 | +| install-plugin | 安装插件命令,用于安装插件。| +| uninstall-plugin | 卸载插件命令,用于卸载插件。| | dump | 查询命令,用来查询应用的相关信息。 | | clean | 清理命令,用来清理应用的缓存和数据。此命令在root版本下可用,在user版本下打开开发者模式可用。其它情况不可用。| | enable | 使能命令,用来使能应用,使能后应用可以继续使用。此命令在root版本下可用,在user版本下不可用。 | @@ -129,6 +131,51 @@ bm uninstall -n com.ohos.example -s -v 100001 bm uninstall -n com.ohos.app -k ``` +#### 安装插件命令 + +```bash +bm install-plugin [-h] [-n hostBundleName] [-p filePath] +``` + +命令可以组合,下面列出部分命令。 + + + **表4** 安装插件命令列表 + +| 命令 | 描述 | +| ----------------------------- | ------------------------ | +| bm install-plugin -h | 显示install-plugin支持的命令信息。-h为非必选字段。 | +| bm install-plugin -n \ -p \| 通过指定主体应用包名和插件文件路径安装插件应用。-n为必选字段,-p为必选字段| + +示例: + +```bash +# 安装一个插件 +bm install-plugin -n com.ohos.app -p /data/app/plugin.hsp +``` + +#### 卸载插件命令 + +```bash +bm uninstall-plugin [-h] [-n hostBundleName] [-p pluginBundleName] +``` + +命令可以组合,下面列出部分命令。 + + + **表4** 卸载插件命令列表 + +| 命令 | 描述 | +| ----------------------------- | ------------------------ | +| bm uninstall-plugin -h | 显示 uninstall-plugin 支持的命令信息。-h为非必选字段。 | +| bm uninstall-plugin -n \ -p \| 通过指定主体应用包名和插件应用包名卸载插件应用。-n为必选字段,-p为必选字段| + +示例: + +```bash +# 卸载一个插件 +bm uninstall-plugin -n com.ohos.app -p com.ohos.plugin +``` #### 查询应用信息命令 diff --git a/frameworks/include/bundle_command.h b/frameworks/include/bundle_command.h index 8888b5a8bd8dc0c8be44b4e71aea5ed3b3c5c137..bd418e6c4ff2b15a43b0be8818230b3737e7df10 100644 --- a/frameworks/include/bundle_command.h +++ b/frameworks/include/bundle_command.h @@ -30,6 +30,8 @@ const std::string HELP_MSG = "usage: bm \n" " help list available commands\n" " install install a bundle with options\n" " uninstall uninstall a bundle with options\n" + " install-plugin install a plugin with options\n" + " uninstall-plugin uninstall a plugin with option\n" " dump dump the bundle info\n" " get obtain device udid\n" " quickfix quick fix, including query and install\n" @@ -176,6 +178,25 @@ const std::string HELP_MSG_DUMP_SHARED_DEPENDENCIES = " -h, --help list available commands\n" " -n, --bundle-name dump dependencies by bundleName and moduleName\n" " -m, --module-name dump dependencies by bundleName and moduleName\n"; +const std::string HELP_MSG_INSTALL_PLUGIN = + "usage: bm install-plugin \n" + "options list:\n" + " -h, --help list available commands\n" + " -n --host-bundle-name -p --plugin-path install a plugin by hsp path and host bundle name\n"; + +const std::string HELP_MSG_UNINSTALL_PLUGIN = + "usage: bm uninstall-plugin \n" + "options list:\n" + " -h, --help list available commands\n" + " -n --host-bundle-name -p --plugin-bundle-name uninstall a plugin by plugin bundle name and host bundle name\n"; + +const std::string HELP_MSG_NO_INSTALL_PLUGIN_OPTION = + "error: you must specify a plugin path with '-p' or '--plugin-path' \n" + "and a host bundle name with '-n' or '--host-bundle-name' \n"; + +const std::string HELP_MSG_NO_UNINSTALL_PLUGIN_OPTION = + "error: you must specify a plugin bundle name with '-p' or '--plugin-bundle-name' \n" + "and a host bundle name with '-n' or '--host-bundle-name' \n"; const std::string STRING_INCORRECT_OPTION = "error: incorrect option"; const std::string HELP_MSG_NO_BUNDLE_PATH_OPTION = @@ -253,6 +274,8 @@ private: ErrCode RunAsDumpSharedCommand(); ErrCode RunAsCompileCommand(); ErrCode RunAsCopyApCommand(); + ErrCode RunAsInstallPluginCommand(); + ErrCode RunAsUninstallPluginCommand(); std::string CopyAp(const std::string &bundleName, bool isAllBundle) const; @@ -295,9 +318,16 @@ private: std::shared_ptr &quickFixRes, bool isDebug, const std::string &targetPath) const; ErrCode DeleteQuickFix(const std::string &bundleName, std::shared_ptr &quickFixRes) const; std::string GetWaringString(int32_t currentUserId, int32_t specifedUserId) const; + ErrCode ParseInstallPluginCommand(int32_t option, std::string &hostBundleName, + std::vector &pluginPaths); + ErrCode GetPluginPath(const std::string& param, std::vector& pluginPaths) const; + int32_t TransformErrCode(const int32_t resultCode); + ErrCode ParseUninstallPluginCommand(int32_t option, std::string &hostBundleName, std::string &pluginBundleName); sptr bundleMgrProxy_; sptr bundleInstallerProxy_; + + static std::map errCodeMap_; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/src/bundle_command.cpp b/frameworks/src/bundle_command.cpp index 915ad2e03c220e93b224f3db39778081d5c649fa..3cca5c6836563cb829c79e23ead54d50ca55b0c2 100644 --- a/frameworks/src/bundle_command.cpp +++ b/frameworks/src/bundle_command.cpp @@ -77,6 +77,22 @@ const struct option LONG_OPTIONS_COPY_AP[] = { {nullptr, 0, nullptr, 0}, }; +const std::string SHORT_OPTIONS_INSTALL_PLUGIN = "hn:p:"; +const struct option LONG_OPTIONS_INSTALL_PLUGIN[] = { + {"help", no_argument, nullptr, 'h'}, + {"host-bundle-name", required_argument, nullptr, 'n'}, + {"plugin-path", required_argument, nullptr, 'p'}, + {nullptr, 0, nullptr, 0}, +}; + +const std::string SHORT_OPTIONS_UNINSTALL_PLUGIN = "hn:p:"; +const struct option LONG_OPTIONS_UNINSTALL_PLUGIN[] = { + {"help", no_argument, nullptr, 'h'}, + {"host-bundle-name", required_argument, nullptr, 'n'}, + {"plugin-bundle-name", required_argument, nullptr, 'p'}, + {nullptr, 0, nullptr, 0}, +}; + const std::string SHORT_OPTIONS = "hp:rn:m:a:cdu:w:s:i:"; const struct option LONG_OPTIONS[] = { {"help", no_argument, nullptr, 'h'}, @@ -198,6 +214,32 @@ bool CleanCacheCallbackImpl::GetResultCode() return false; } +std::map BundleManagerShellCommand::errCodeMap_ = { + {ERR_APPEXECFWK_PLUGIN_INSTALL_PARAM_ERROR, IStatusReceiver::ERR_INSTALL_PARAM_ERROR}, + {ERR_APPEXECFWK_PLUGIN_INSTALL_CHECK_PLUGINID_ERROR, IStatusReceiver::ERR_PLUGIN_INSTALL_CHECK_PLUGINID_ERROR}, + {ERR_APPEXECFWK_SUPPORT_PLUGIN_PERMISSION_ERROR, IStatusReceiver::ERR_PLUGIN_SUPPORT_PLUGIN_PERMISSION_ERROR}, + {ERR_APPEXECFWK_HOST_APPLICATION_NOT_FOUND, IStatusReceiver::ERR_HOST_APP_NOT_FOUND}, + {ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE, IStatusReceiver::ERR_INSTALL_VERSION_DOWNGRADE}, + {ERR_APPEXECFWK_INSTALL_FAILED_INCONSISTENT_SIGNATURE, IStatusReceiver::ERR_INSTALL_FAILED_INCONSISTENT_SIGNATURE}, + {ERR_APPEXECFWK_PLUGIN_PARSER_ERROR, IStatusReceiver::ERR_INSTALL_PARSE_FAILED}, + {ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID, IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID}, + {ERR_APPEXECFWK_INSTALL_INVALID_BUNDLE_FILE, IStatusReceiver::ERR_INSTALL_INVALID_BUNDLE_FILE}, + {ERR_APPEXECFWK_INSTALL_INVALID_HAP_SIZE, IStatusReceiver::ERR_INSTALL_INVALID_HAP_SIZE}, + {ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE, IStatusReceiver::ERR_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE}, + {ERR_APPEXECFWK_INSTALL_FAILED_BUNDLE_SIGNATURE_VERIFICATION_FAILURE, + IStatusReceiver::ERR_INSTALL_FAILED_BUNDLE_SIGNATURE_VERIFICATION_FAILURE}, + {ERR_APPEXECFWK_INSTALL_PERMISSION_DENIED, IStatusReceiver::ERR_INSTALL_PERMISSION_DENIED}, + {ERR_APPEXECFWK_INSTALL_SYSCAP_FAILED_AND_DEVICE_TYPE_ERROR, + IStatusReceiver::ERR_INSTALL_CHECK_SYSCAP_FAILED_AND_DEVICE_TYPE_NOT_SUPPORTED}, + {ERR_APPEXECFWK_USER_NOT_EXIST, IStatusReceiver::ERR_USER_NOT_EXIST}, + {ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FAILED, IStatusReceiver::ERR_INSTALL_CODE_SIGNATURE_FAILED}, + {ERR_APPEXECFWK_DEVICE_NOT_SUPPORT_PLUGIN, IStatusReceiver::ERR_DEVICE_NOT_SUPPORT_PLUGIN}, + {ERR_APPEXECFWK_PLUGIN_CHECK_APP_LABEL_ERROR, IStatusReceiver::ERR_MULTIPLE_HSP_INFO_INCONSISTENT}, + {ERR_APPEXECFWK_INSTALL_DEBUG_BUNDLE_NOT_ALLOWED, IStatusReceiver::ERR_INSTALL_DEBUG_BUNDLE_NOT_ALLOWED}, + {ERR_APPEXECFWK_PLUGIN_INSTALL_PARSE_PLUGINID_ERROR, IStatusReceiver::ERR_PLUGIN_ID_PARSE_FAILED}, + {ERR_APPEXECFWK_PLUGIN_NOT_FOUND, IStatusReceiver::ERR_PLUGIN_APP_NOT_FOUND} +}; + BundleManagerShellCommand::BundleManagerShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, TOOL_NAME) {} @@ -207,6 +249,8 @@ ErrCode BundleManagerShellCommand::CreateCommandMap() {"help", [this] { return this->RunAsHelpCommand(); } }, {"install", [this] { return this->RunAsInstallCommand(); } }, {"uninstall", [this] { return this->RunAsUninstallCommand(); } }, + {"install-plugin", [this] { return this->RunAsInstallPluginCommand(); } }, + {"uninstall-plugin", [this] { return this->RunAsUninstallPluginCommand(); } }, {"dump", [this] { return this->RunAsDumpCommand(); } }, {"clean", [this] { return this->RunAsCleanCommand(); } }, {"enable", [this] { return this->RunAsEnableCommand(); } }, @@ -740,6 +784,20 @@ ErrCode BundleManagerShellCommand::GetBundlePath(const std::string& param, return OHOS::ERR_OK; } +ErrCode BundleManagerShellCommand::GetPluginPath(const std::string& param, + std::vector& pluginPaths) const +{ + if (param.empty()) { + return OHOS::ERR_INVALID_VALUE; + } + if (param == "-p" || param == "--plugin-path" || + param == "-n" || param == "--host-bundle-name") { + return OHOS::ERR_INVALID_VALUE; + } + pluginPaths.emplace_back(param); + return OHOS::ERR_OK; +} + ErrCode BundleManagerShellCommand::RunAsUninstallCommand() { APP_LOGI("begin to RunAsUninstallCommand"); @@ -2808,5 +2866,222 @@ std::string BundleManagerShellCommand::GetWaringString(int32_t currentUserId, in } return res; } + +int32_t BundleManagerShellCommand::TransformErrCode(const int32_t resultCode) +{ + if (errCodeMap_.find(resultCode) != errCodeMap_.end()) { + return errCodeMap_.at(resultCode); + } + return IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR; +} + +ErrCode BundleManagerShellCommand::RunAsInstallPluginCommand() +{ + APP_LOGI("begin to RunAsInstallPluginCommand"); + int result = OHOS::ERR_OK; + std::string hostBundleName; + std::vector pluginPaths; + int32_t userId = BundleCommandCommon::GetCurrentUserId(Constants::UNSPECIFIED_USERID); + int32_t option; + while ((option = getopt_long(argc_, argv_, SHORT_OPTIONS_INSTALL_PLUGIN.c_str(), + LONG_OPTIONS_INSTALL_PLUGIN, nullptr)) != -1) { + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + result = ParseInstallPluginCommand(option, hostBundleName, pluginPaths); + } + if (result == OHOS::ERR_OK) { + if (resultReceiver_ == "" && (pluginPaths.empty() || hostBundleName.empty())) { + APP_LOGD("'bm install-plugin' with no bundle path option."); + resultReceiver_.append(HELP_MSG_NO_INSTALL_PLUGIN_OPTION + "\n"); + result = OHOS::ERR_INVALID_VALUE; + } + } + if (result != OHOS::ERR_OK) { + resultReceiver_.append(HELP_MSG_INSTALL_PLUGIN); + } else { + InstallPluginParam installPluginParam; + installPluginParam.userId = userId; + std::vector pathVec; + GetAbsPaths(pluginPaths, pathVec); + int32_t installResult = bundleInstallerProxy_->InstallPlugin(hostBundleName, pathVec, installPluginParam); + if (installResult == OHOS::ERR_OK) { + resultReceiver_ = STRING_INSTALL_BUNDLE_OK + "\n"; + } else { + int32_t res = TransformErrCode(installResult); + resultReceiver_ = STRING_INSTALL_BUNDLE_NG + "\n"; + resultReceiver_.append(GetMessageFromCode(res)); + } + } + APP_LOGI("RunAsInstallPluginCommand end"); + return result; +} + +ErrCode BundleManagerShellCommand::ParseInstallPluginCommand(int32_t option, std::string &hostBundleName, + std::vector &pluginPaths) +{ + int32_t result = OHOS::ERR_OK; + if (option == '?') { + switch (optopt) { + case 'n': { + // 'bm install-plugin -n' with no argument: bm install-plugin -n + // 'bm install-plugin --host-bundle-name' with no argument: bm install-plugin --host-bundle-name + APP_LOGD("'bm install-plugin -n' with no argument."); + resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE); + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'p': { + // 'bm install-plugin -p' with no argument: bm install-plugin -p + // 'bm install-plugin --plugin-path' with no argument: bm install-plugin --plugin-path + APP_LOGD("'bm install-plugin -p' with no argument."); + resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE); + result = OHOS::ERR_INVALID_VALUE; + break; + } + default: { + // 'bm install-plugin' with an unknown option: bm dump-shared -x + // 'bm install-plugin' with an unknown option: bm dump-shared -xxx + std::string unknownOption = ""; + std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption); + resultReceiver_.append(unknownOptionMsg); + result = OHOS::ERR_INVALID_VALUE; + break; + } + } + } else { + switch (option) { + case 'h': { + // 'bm install-plugin -h' + // 'bm install-plugin --help' + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'n': { + // 'bm install-plugin -n xxx' + // 'bm install-plugin --host-bundle-name xxx' + hostBundleName = optarg; + break; + } + case 'p': { + // 'bm install-plugin -p xxx' + // 'bm install-plugin --plugin-path xxx' + APP_LOGD("'bm install-plugin %{public}s'", argv_[optind - 1]); + if (GetPluginPath(optarg, pluginPaths) != OHOS::ERR_OK) { + resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE); + return OHOS::ERR_INVALID_VALUE; + } + break; + } + default: { + result = OHOS::ERR_INVALID_VALUE; + break; + } + } + } + return result; +} +ErrCode BundleManagerShellCommand::RunAsUninstallPluginCommand() +{ + APP_LOGI("begin to RunAsUninstallPluginCommand"); + int result = OHOS::ERR_OK; + std::string hostBundleName; + std::string pluginBundleName; + int32_t userId = BundleCommandCommon::GetCurrentUserId(Constants::UNSPECIFIED_USERID); + int32_t option; + while ((option = getopt_long(argc_, argv_, SHORT_OPTIONS_UNINSTALL_PLUGIN.c_str(), + LONG_OPTIONS_UNINSTALL_PLUGIN, nullptr)) != -1) { + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + result = ParseUninstallPluginCommand(option, hostBundleName, pluginBundleName); + } + if (result == OHOS::ERR_OK) { + if (resultReceiver_ == "" && (pluginBundleName.empty() || hostBundleName.empty())) { + APP_LOGD("'bm uninstall-plugin' with no bundle path option."); + resultReceiver_.append(HELP_MSG_NO_UNINSTALL_PLUGIN_OPTION + "\n"); + result = OHOS::ERR_INVALID_VALUE; + } + } + if (result != OHOS::ERR_OK) { + resultReceiver_.append(HELP_MSG_UNINSTALL_PLUGIN); + } else { + InstallPluginParam installPluginParam; + installPluginParam.userId = userId; + int32_t installResult = + bundleInstallerProxy_->UninstallPlugin(hostBundleName, pluginBundleName, installPluginParam); + if (installResult == OHOS::ERR_OK) { + resultReceiver_ = STRING_UNINSTALL_BUNDLE_OK + "\n"; + } else { + int32_t res = TransformErrCode(installResult); + resultReceiver_ = STRING_UNINSTALL_BUNDLE_NG + "\n"; + resultReceiver_.append(GetMessageFromCode(res)); + } + } + APP_LOGI("RunAsUninstallPluginCommand end"); + return result; +} + +ErrCode BundleManagerShellCommand::ParseUninstallPluginCommand(int32_t option, std::string &hostBundleName, + std::string &pluginBundleName) +{ + int32_t result = OHOS::ERR_OK; + if (option == '?') { + switch (optopt) { + case 'n': { + // 'bm uninstall-plugin -n' with no argument: bm uninstall-plugin -n + // 'bm uninstall-plugin --host-bundle-name' with no argument: bm uninstall-plugin --host-bundle-name + APP_LOGD("'bm uninstall-plugin -n' with no argument."); + resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE); + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'p': { + // 'bm uninstall-plugin -p' with no argument: bm uninstall-plugin -p + // 'bm uninstall-plugin --plugin-bundle-name' with no argument: bm uninstall-plugin --plugin-bundle-name + APP_LOGD("'bm uninstall-plugin -p' with no argument."); + resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE); + result = OHOS::ERR_INVALID_VALUE; + break; + } + default: { + // 'bm uninstall-plugin' with an unknown option: bm uninstall-plugin -x + // 'bm uninstall-plugin' with an unknown option: bm uninstall-plugin -xxx + std::string unknownOption = ""; + std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption); + resultReceiver_.append(unknownOptionMsg); + result = OHOS::ERR_INVALID_VALUE; + break; + } + } + } else { + switch (option) { + case 'h': { + // 'bm uninstall-plugin -h' + // 'bm uninstall-plugin --help' + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'n': { + // 'bm uninstall-plugin -n xxx' + // 'bm uninstall-plugin --host-bundle-name xxx' + hostBundleName = optarg; + break; + } + case 'p': { + // 'bm uninstall-plugin -p xxx' + // 'bm uninstall-plugin --plugin-bundle-name xxx' + APP_LOGD("'bm uninstall-plugin %{public}s'", argv_[optind - 1]); + pluginBundleName = optarg; + break; + } + default: { + result = OHOS::ERR_INVALID_VALUE; + break; + } + } + } + return result; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/src/bundle_command_common.cpp b/frameworks/src/bundle_command_common.cpp index 142ac93b492d4d2810e47c3ebc81a0810aca3863..b4efaaa4a5002b5fb7e1608d8b5c3d48b7adb47a 100644 --- a/frameworks/src/bundle_command_common.cpp +++ b/frameworks/src/bundle_command_common.cpp @@ -723,6 +723,34 @@ std::map BundleCommandCommon::bundleMessageMap_ = { IStatusReceiver::ERR_APP_DISTRIBUTION_TYPE_NOT_ALLOW_INSTALL_ISR, "error: Failed to install the HAP or HSP because the app distribution type is not allowed." }, + { + IStatusReceiver::ERR_PLUGIN_INSTALL_CHECK_PLUGINID_ERROR, + "error: Check pluginDistributionID between plugin and host application failed." + }, + { + IStatusReceiver::ERR_PLUGIN_SUPPORT_PLUGIN_PERMISSION_ERROR, + "error: Failed to install the plugin because host application check permission failed." + }, + { + IStatusReceiver::ERR_HOST_APP_NOT_FOUND, + "error: Host application is not found." + }, + { + IStatusReceiver::ERR_DEVICE_NOT_SUPPORT_PLUGIN, + "error: Failed to install the plugin because current device does not support plugin." + }, + { + IStatusReceiver::ERR_MULTIPLE_HSP_INFO_INCONSISTENT, + "error: Failed to install the plugin because they have different configuration information." + }, + { + IStatusReceiver::ERR_PLUGIN_ID_PARSE_FAILED, + "error: Failed to install the plugin because the plugin id failed to be parsed." + }, + { + IStatusReceiver::ERR_PLUGIN_APP_NOT_FOUND, + "error: The plugin is not found." + } }; } // AppExecFwk } // OHOS \ No newline at end of file