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

Posted 开源基础软件社区官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Open Harmony——包管理子系统包安装模块源码解析相关的知识,希望对你有一定的参考价值。

作者:李小慧

简介

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

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

代码目录

foundation/appexecfwk/standard
├── kits
│   └── appkit                  # Appkit实现的核心代码
├── common
│   └── log                     # 日志组件目录
├── interfaces
│   └── innerkits               # 内部接口存放目录
├── services
│   └── bundlemgr               # 包管理服务框架代码
│   └── dbms                    # 分布式包管理服务框架代码
├── test                        # 测试目录
└── tools                       # bm命令存放目录        

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

类图

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 包安装基类,实现安装、卸载包功能。

第三方应用包安装流程图

源码分析

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

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

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

```c++
//注册模块
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

```C++
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
                
            ,
            ...

```C++
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 %publics", installResult.resultMsg.c_str());
installResult.resultCode = callback->GetResultCode();
APP_LOGD("InnerInstall resultCode %publicd", installResult.resultCode);


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

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

```C++
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);//发送安装消息

```C++
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: %publicd", ret);
    return false;

return true;


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

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

```C++
int BundleInstallerHost::OnRemoteRequest(
    uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)

    APP_LOGD("bundle installer host onReceived message, the message code is %publicu", 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

```C++
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_FLAGLOG);
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

```C++
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

```C++
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;


## 系统应用包安装流程图

![systeminstall.png](https://dl-harmonyos.51cto.com/images/202205/d236cab14659ae6e8b4956d6e004f9c6aa050e.png?x-oss-process=image/resize,w_626,h_537)

### 源码分析

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

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

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

```c++
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: %publics and userId: %publicd", 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 %publics", item.c_str());
        if (!installer.InstallSystemBundle(appType, userId)) //调用安装系统包流程
            APP_LOGW("Install System app:%publics error", item.c_str());
        
    

    PerfProfile::GetInstance().Dump();

2. 调用 SystemBundleInstaller的InstallSystemBundle流程

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

```c++
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_SYSTEMAPP)
installParam.needSavePreInstallInfo = true;

ErrCode result = InstallBundle(filePath
, installParam, appType);
if (result != ERR_OK)
APP_LOGE("install system bundle fail, error: %publicd", result);
return false;

return true;


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

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

```C++
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

以上是关于Open Harmony——包管理子系统包安装模块源码解析的主要内容,如果未能解决你的问题,请参考以下文章

NPM 的包管理

python中如何安装SciPY模块

cygwin 安装包管理器 apt-cyg

在Mac系统下python如何安装第三方函数库?

Open Harmony移植:build lite配置目录全梳理

在Mac系统下python如何安装第三方函数库?