4

Open Harmony——包管理子系统包安装模块源码解析

 2 years ago
source link: https://blog.51cto.com/harmonyos/5354117
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者:李小慧

包管理子系统负责应用安装包的管理,提供安装包的信息查询、安装、更新、卸载和包信息存储等能力。

包管理子系统架构如下图所示:

Open Harmony——包管理子系统包安装模块源码解析_开鸿HarmonyOS
foundation/appexecfwk/standard
├── kits
│   └── appkit					# Appkit实现的核心代码
├── common
│   └── log					    # 日志组件目录
├── interfaces
│   └── innerkits				# 内部接口存放目录
├── services
│   └── bundlemgr	            # 包管理服务框架代码
│   └── dbms	                # 分布式包管理服务框架代码
├── test						# 测试目录
└── tools                       # bm命令存放目录        

包安装类间关系及关键类介绍

Open Harmony——包管理子系统包安装模块源码解析_应用程序_02

BaseBundleInstaller是安装流程中最重要的类,最终的安装、卸载功能都是在其中实现的。

IBundleMgr中定义了获取IBundleInstaller实例的方法GetBundleInstaller。

IBundleInstaller类是BundleInstallerProxy和BundleInstallerHost的基类,只是在类中声明了Install,Uninstall等函数,具体实现是在这两个子类中实现的。

BundleInstallerProxy类实现了Install,Uninstall功能,利用IPC Proxy向service层发送安装或卸载请求。

服务层Host接收到Proxy发送过来的请求处理消息,调用BundleInstallerHost类的Install功能,调用BundleInstallerManager类的创建安装任务CreateInstallTask函数,在此函数中调用BundleInstaller类的Install功能。

BundleInstaller类的基类是BaseBundleInstaller,它的Install功能实际上调用的是BaseBundleInstaller类的InstallBundle函数。

BMSEventHandler类是继承EventHandler类的,由它来处理系统应用包的安装。它调用SystemBundleInstaller类的InstallSystemBundle函数。

SystemBundleInstaller类也是BaseBundleInstaller的子类,所以最终调用的还是BaseBundleInstaller的InstallBundle功能。

关键类介绍

类名 功能简介
IBundleMgr 包管理类,声明了获取和查询APP信息、包信息等接口。
IBundleInstaller 包安装类,声明了安装、卸载等接口。
BundleInstallerProxy interface层包安装代理类,继承了IBundleInstaller类,实现了安装、卸载等功能。
BundleInstallerHost service层host侧包安装类,继承了IBundleInstaller类,处理来自proxy的安装、卸载信息,实现了host侧安装、卸载等功能,。
BundleInstallerManager 包安装服务类,创建安装、卸载等任务。
BundleInstaller 包安装类,实现安装、卸载第三方应用包功能。
BMSEventHandler 继承EventHandler,实现了处理系统应用包安装等功能。
SystemBundleInstaller 系统应用包安装类,实现安装、卸载系统应用包功能。
BaseBundleInstaller 包安装基类,实现安装、卸载包功能。

第三方应用包安装流程图

Open Harmony——包管理子系统包安装模块源码解析_开鸿HarmonyOS_03

由于流程较为复杂,受篇幅限制,此处摘取流程中重要的代码段进行说明。详细的代码流程需要对照OpenHarmony源码进行学习。

1. 包管理的NAPI Init()函数中注册包安装install

foundation\appexecfwk\standard\kits\appkit\napi\bundlemgr\native_module.cpp

//注册模块
extern "C" __attribute__((constructor)) void RegisterModule(void)
{
    napi_module_register(&_module);
}
//包模块描述
static napi_module _module = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "bundle",
    .nm_priv = ((void *)0),
    .reserved = {0}
};
//初始化
static napi_value Init(napi_env env, napi_value exports)
{
    ...
    napi_property_descriptor properties[] = {
        DECLARE_NAPI_FUNCTION("install", Install),//调用Install流程
        DECLARE_NAPI_FUNCTION("recover", Recover),
        DECLARE_NAPI_FUNCTION("uninstall", Uninstall),
    };
    NAPI_CALL(env,
        napi_define_class(env,
            "BundleInstaller",
            NAPI_AUTO_LENGTH,
            BundleInstallerConstructor,
            nullptr,
            sizeof(properties) / sizeof(*properties),
            properties,
            &m_classBundleInstaller));
}

2. 调用 bundle_mgr.c中的 Install

foundation\appexecfwk\standard\kits\appkit\napi\bundlemgr\bundle_mgr.cpp

napi_value Install(napi_env env, napi_callback_info info)
{
   ...
    napi_create_async_work(
            env,
            nullptr,
            resourceName,
            [](napi_env env, void *data) {
                AsyncInstallCallbackInfo *asyncCallbackInfo = (AsyncInstallCallbackInfo *)data;
                if (!asyncCallbackInfo->errCode) {
                    InnerInstall(env,
                        asyncCallbackInfo->hapFiles,
                        asyncCallbackInfo->installParam,
                        asyncCallbackInfo->installResult);//调用InnerInstall
                }
            },
            ...
}
static void InnerInstall(napi_env env, const std::vector<std::string> &bundleFilePath, InstallParam &installParam,
    InstallResult &installResult)
{
    if (bundleFilePath.empty()) {
        installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID);
        return;
    }
    auto iBundleMgr = GetBundleMgr();
    if (!iBundleMgr) {
        APP_LOGE("can not get iBundleMgr");
        return;
    }
    auto iBundleInstaller = iBundleMgr->GetBundleInstaller();
    if ((iBundleInstaller == nullptr) || (iBundleInstaller->AsObject() == nullptr)) {
        APP_LOGE("can not get iBundleInstaller");
        return;
    }
    installParam.installFlag = InstallFlag::REPLACE_EXISTING;
    OHOS::sptr<InstallerCallback> callback = new InstallerCallback();
    if (!callback) {
        APP_LOGE("callback nullptr");
        return;
    }

    sptr<BundleDeathRecipient> recipient(new BundleDeathRecipient(callback));
    iBundleInstaller->AsObject()->AddDeathRecipient(recipient);
    iBundleInstaller->Install(bundleFilePath, installParam, callback);//调用IBundleInstaller的Install
    installResult.resultMsg = callback->GetResultMsg();
    APP_LOGD("InnerInstall resultMsg %{public}s", installResult.resultMsg.c_str());
    installResult.resultCode = callback->GetResultCode();
    APP_LOGD("InnerInstall resultCode %{public}d", installResult.resultCode);
}

3. IBundleInstaller的Install在继承类BundleInstallerProxy 中实现,发送安装消息

foundation\appexecfwk\standard\interfaces\innerkits\appexecfwk_core\src\bundlemgr\bundle_installer_proxy.cpp

bool BundleInstallerProxy::Install(
    const std::string &bundlePath, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
{
    BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);

    PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
    PARCEL_WRITE(data, String16, Str8ToStr16(bundlePath));
    PARCEL_WRITE(data, Parcelable, &installParam);

    if (!statusReceiver) {
        APP_LOGE("fail to install, for statusReceiver is nullptr");
        return false;
    }
    if (!data.WriteObject<IRemoteObject>(statusReceiver->AsObject())) {
        APP_LOGE("write parcel failed");
        return false;
    }

    return SendInstallRequest(static_cast<int32_t>(IBundleInstaller::Message::INSTALL), data, reply, option);//发送安装消息
}

bool BundleInstallerProxy::SendInstallRequest(const int32_t& code, MessageParcel& data, MessageParcel& reply,
    MessageOption& option)
{
    sptr<IRemoteObject> remote = Remote();
    if (!remote) {
        APP_LOGE("fail to uninstall, for Remote() is nullptr");
        return false;
    }

    int32_t ret = remote->SendRequest(code, data, reply, option);//发送安装消息
    if (ret != NO_ERROR) {
        APP_LOGE("fail to sendRequest, for transact is failed and error code is: %{public}d", ret);
        return false;
    }
    return true;
}

4. 在service层host侧处理安装消息

foundation\appexecfwk\standard\services\bundlemgr\src\bundle_installer_host.cpp

int BundleInstallerHost::OnRemoteRequest(
    uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
    APP_LOGD("bundle installer host onReceived message, the message code is %{public}u", code);
    std::u16string descripter = GetDescriptor();
    std::u16string remoteDescripter = data.ReadInterfaceToken();
    if (descripter != remoteDescripter) {
        APP_LOGE("fail to write reply message in bundle mgr host due to the reply is nullptr");
        return OBJECT_NULL;
    }

    switch (code) {
        case static_cast<uint32_t>(IBundleInstaller::Message::INSTALL):
            HandleInstallMessage(data);//处理安装消息
            break;
        case static_cast<uint32_t>(IBundleInstaller::Message::INSTALL_MULTIPLE_HAPS):
            HandleInstallMultipleHapsMessage(data);
            break;
        case static_cast<uint32_t>(IBundleInstaller::Message::UNINSTALL):
            HandleUninstallMessage(data);
            break;
        case static_cast<uint32_t>(IBundleInstaller::Message::UNINSTALL_MODULE):
            HandleUninstallModuleMessage(data);
            break;
        case static_cast<uint32_t>(IBundleInstaller::Message::RECOVER):
            HandleRecoverMessage(data);
            break;
        default:
            return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
    }
    return NO_ERROR;
}

void BundleInstallerHost::HandleInstallMessage(Parcel &data)
{
    APP_LOGD("handle install message");
    std::string bundlePath = Str16ToStr8(data.ReadString16());
    std::unique_ptr<InstallParam> installParam(data.ReadParcelable<InstallParam>());
    if (!installParam) {
        APP_LOGE("ReadParcelable<InstallParam> failed");
        return;
    }
    sptr<IRemoteObject> object = data.ReadObject<IRemoteObject>();
    if (object == nullptr) {
        APP_LOGE("read failed");
        return;
    }
    sptr<IStatusReceiver> statusReceiver = iface_cast<IStatusReceiver>(object);

    Install(bundlePath, *installParam, statusReceiver);//调用安装函数
    APP_LOGD("handle install message finished");
}

bool BundleInstallerHost::Install(
    const std::string &bundleFilePath, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
{
    if (!CheckBundleInstallerManager(statusReceiver)) {
        APP_LOGE("statusReceiver invalid");
        return false;
    }
    if (!BundlePermissionMgr::VerifyCallingPermission(Constants::PERMISSION_INSTALL_BUNDLE)) {
        APP_LOGE("install permission denied");
        statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_PERMISSION_DENIED, "");
        return false;
    }

    manager_->CreateInstallTask(bundleFilePath, CheckInstallParam(installParam), statusReceiver);//创建安装任务
    return true;
}

5. 在service层bundlemgr侧创建安装任务

foundation\appexecfwk\standard\services\bundlemgr\src\bundle_installer_manager.cpp

void BundleInstallerManager::CreateInstallTask(
    const std::string &bundleFilePath, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
{
    auto installer = CreateInstaller(statusReceiver);
    if (!installer) {
        APP_LOGE("create installer failed");
        return;
    }
    auto task = [installer, bundleFilePath, installParam] {
        int timerId = HiviewDFX::XCollie::GetInstance().SetTimer(INSTALL_TASK, TIME_OUT_SECONDS,
            nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG);
        installer->Install(bundleFilePath, installParam);//调用BundleInstaller的Install函数
        HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
    };
    installersPool_.AddTask(task);
}

6. 在service层bundlemgr侧安装第三方应用包

foundation\appexecfwk\standard\services\bundlemgr\src\bundle_installer.cpp

void BundleInstaller::Install(const std::string &bundleFilePath, const InstallParam &installParam)
{
    ErrCode resultCode = ERR_OK;
    if (installParam.userId == Constants::ALL_USERID) {
        auto userInstallParam = installParam;
        for (auto userId : GetExistsCommonUserIs()) {
            userInstallParam.userId = userId;
            userInstallParam.installFlag = InstallFlag::REPLACE_EXISTING;
            resultCode = InstallBundle(
                bundleFilePath, userInstallParam, Constants::AppType::THIRD_PARTY_APP);//安装第三方应用的包
            ResetInstallProperties();
        }
    } else {
        resultCode = InstallBundle(
            bundleFilePath, installParam, Constants::AppType::THIRD_PARTY_APP);//安装第三方应用的包
    }

    statusReceiver_->OnFinished(resultCode, "");
    SendRemoveEvent();
}

7. 调用BundleInstaller基类BaseBundleInstaller的InstallBundle函数

foundation\appexecfwk\standard\services\bundlemgr\src\base_bundle_installer.cpp

ErrCode BaseBundleInstaller::InstallBundle(
    const std::string &bundlePath, const InstallParam &installParam, const Constants::AppType appType)
{
    std::vector<std::string> bundlePaths { bundlePath };
    return InstallBundle(bundlePaths, installParam, appType);
}

ErrCode BaseBundleInstaller::InstallBundle(
    const std::vector<std::string> &bundlePaths, const InstallParam &installParam, const Constants::AppType appType)
{
    BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
    APP_LOGD("begin to process bundle install");

    PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());

    int32_t uid = Constants::INVALID_UID;
    ErrCode result = ProcessBundleInstall(bundlePaths, installParam, appType, uid);//处理包安装的具体流程
    if (installParam.needSendEvent && dataMgr_ && !bundleName_.empty()) {
        dataMgr_->NotifyBundleStatus(bundleName_,
            Constants::EMPTY_STRING,
            mainAbility_,
            result,
            isAppExist_ ? NotifyType::UPDATE : NotifyType::INSTALL,
            uid);//包安装完成后反馈包安装状态
    }

    PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
    APP_LOGD("finish to process bundle install");
    return result;
}

系统应用包安装流程图

Open Harmony——包管理子系统包安装模块源码解析_应用程序_04

限于篇幅,每个调用函数只摘抄关键语句。

1. 系统应用包安装,调用EventHandler类的继承类BMSEventHandler的ProcessEvent函数

foundation\appexecfwk\standard\services\bundlemgr\src\bundle_mgr_service_event_handler.cpp

void BMSEventHandler::ProcessEvent(const InnerEvent::Pointer &event)
{
    switch (event->GetInnerEventId()) {
        case BUNDLE_SCAN_START: {
            OnStartScanning(Constants::DEFAULT_USERID);//启动扫描
            SetAllInstallFlag();
            DelayedSingleton<BundleMgrService>::GetInstance()->RegisterService();
            break;
        }
        case BUNDLE_SCAN_FINISHED:
            break;
        case BMS_START_FINISHED:
            break;
        case BUNDLE_REBOOT_SCAN_START: {
            RebootStartScanning();
            SetAllInstallFlag();
            DelayedSingleton<BundleMgrService>::GetInstance()->RegisterService();
            break;
        }
        default:
            APP_LOGE("the eventId is not supported");
            break;
    }
}
void BMSEventHandler::OnStartScanning(int32_t userId)
{
    auto future = std::async(std::launch::async, [this, userId] {
        ProcessSystemBundleInstall(Constants::AppType::SYSTEM_APP, userId);//处理系统应用包安装
        ProcessSystemBundleInstall(Constants::AppType::THIRD_SYSTEM_APP, userId);//处理第三方系统应用包安装
    });
    future.get();
}

void BMSEventHandler::ProcessSystemBundleInstall(Constants::AppType appType, int32_t userId) const
{
    APP_LOGD("scan thread start");
    auto scanner = std::make_unique<BundleScanner>();
    if (!scanner) {
        APP_LOGE("make scanner failed");
        return;
    }

    std::string scanDir = (appType == Constants::AppType::SYSTEM_APP) ? Constants::SYSTEM_APP_SCAN_PATH
                                                                      : Constants::THIRD_SYSTEM_APP_SCAN_PATH;
    APP_LOGD("scanDir: %{public}s and userId: %{public}d", scanDir.c_str(), userId);
    std::list<std::string> bundleList = scanner->Scan(scanDir);
    auto 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 (const auto &item : bundleList) {
        SystemBundleInstaller installer(item);
        APP_LOGD("scan item %{public}s", item.c_str());
        if (!installer.InstallSystemBundle(appType, userId)) {//调用安装系统包流程
            APP_LOGW("Install System app:%{public}s error", item.c_str());
        }
    }

    PerfProfile::GetInstance().Dump();
}

2. 调用 SystemBundleInstaller的InstallSystemBundle流程

foundation\appexecfwk\standard\services\bundlemgr\src\system_bundle_installer.cpp

bool SystemBundleInstaller::InstallSystemBundle(Constants::AppType appType, int32_t userId)
{
    InstallParam installParam;
    installParam.userId = userId;
    installParam.isPreInstallApp = true;
    installParam.noSkipsKill = false;
    installParam.needSendEvent = false;
    if (appType == Constants::AppType::SYSTEM_APP
        || appType == Constants::AppType::THIRD_SYSTEM_APP) {
        installParam.needSavePreInstallInfo = true;
    }
    ErrCode result = InstallBundle(filePath_, installParam, appType);
    if (result != ERR_OK) {
        APP_LOGE("install system bundle fail, error: %{public}d", result);
        return false;
    }
    return true;
}

3. 与第三方应用包的安装流程一样,系统应用包安装也是调用SystemBundleInstaller的基类BaseBundleInstaller的InstallBundle函数

foundation\appexecfwk\standard\services\bundlemgr\src\base_bundle_installer.cpp

ErrCode BaseBundleInstaller::InstallBundle(
    const std::string &bundlePath, const InstallParam &installParam, const Constants::AppType appType)
{
    std::vector<std::string> bundlePaths { bundlePath };
    return InstallBundle(bundlePaths, installParam, appType);
}

ErrCode BaseBundleInstaller::InstallBundle(
    const std::vector<std::string> &bundlePaths, const InstallParam &installParam, const Constants::AppType appType)
{
    BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
    APP_LOGD("begin to process bundle install");

    PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());

    int32_t uid = Constants::INVALID_UID;
    ErrCode result = ProcessBundleInstall(bundlePaths, installParam, appType, uid);//处理包安装的具体流程
    if (installParam.needSendEvent && dataMgr_ && !bundleName_.empty()) {
        dataMgr_->NotifyBundleStatus(bundleName_,
            Constants::EMPTY_STRING,
            mainAbility_,
            result,
            isAppExist_ ? NotifyType::UPDATE : NotifyType::INSTALL,
            uid);//包安装完成后反馈包安装状态
    }

    PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
    APP_LOGD("finish to process bundle install");
    return result;
}

本文主要介绍了包管理子系统的关键实现机制、主要类关系及重要的处理流程,为开发人员维护和扩展功能提供参考。

更多原创内容请关注: 深开鸿技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

 想了解更多关于开源的内容,请访问:

 51CTO 开源基础软件社区

 https://ost.51cto.com/#bkwz


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK