PackageInstaller源码分析(二)

本文深入分析了Android的PackageInstaller组件在新App安装和App更新时的处理流程。首先,新App安装从installNewPackageLI()开始,涉及包名校验、扫描APK、更新设置及删除未安装完成的App。核心在于updateSettingsLI()更新系统设置文件。接着,App更新从replacePackageLI()开始,系统App更新会杀死应用进程并删除相关数据,然后更新设置;非系统App更新则删除旧App并接入新App信息。所有更新过程中,writeLPr()函数更新了权限相关文件,实现权限授予。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  上篇PackageInstaller源码分析(一)对PackageInstaller源码分析了一半,本篇接着分析,分别分析对于App更新和新App安装的处理。

一、 新App的安装

  新App的安装从installNewPackageLI()开始,我们查看其源码。

private void installNewPackageLI(PackageParser.Package pkg,
        int parseFlags, int scanFlags, UserHandle user,
        String installerPackageName, PackageInstalledInfo res) {

    ````

    boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
    synchronized(mPackages) {
        if (mSettings.mRenamedPackages.containsKey(pkgName)) {
            // A package with the same name is already installed, though
            // it has been renamed to an older name.  The package we
            // are trying to install should be installed as an update to
            // the existing one, but that has not been requested, so bail.
            res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                    + " without first uninstalling package running as "
                    + mSettings.mRenamedPackages.get(pkgName));
            return;
        }
        if (mPackages.containsKey(pkgName)) {
            // Don't allow installation over an existing package with the same name.
            res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                    + " without first uninstalling.");
            return;
        }
    }

    ````    

}

  这段代码首先判断了是否建立了App的data数据目录。而后,对于要安装的app的包名若已存在的情况作了处理。对于包名已经存在,但是并非更新的情况,抛出异常。

  紧接着,程序调用scanPackageLI()重新获取apk的Package结构,这个函数比较复杂,就是从apk中提取有用信息,这个和PackageInstaller源码分析(一)中PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile)应该是非常类似的,后面再选择一个分析。而后,调用updateSettingsLI()将安装的App写入设置,最后判断App是否完整安装,若没有完整安装,则调用deletePackageLI()将未完整安装的App删除,包括建立的data目录和cache目录。关于这个,在此处不做分析,这些操作和卸载App一定的相似性。以下将分析安装app细节的核心函数updateSettingsLI()。

private void installNewPackageLI(PackageParser.Package pkg,
        int parseFlags, int scanFlags, UserHandle user,
        String installerPackageName, PackageInstalledInfo res) {

    ````

    try {
         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
                 System.currentTimeMillis(), user);

         updateSettingsLI(newPackage, installerPackageName, null, null, res);
         // delete the partially installed application. the data directory will have to be
         // restored if it was already existing
         if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
             // remove package from internal structures.  Note that we want deletePackageX to
             // delete the package data and cache directories that it created in
             // scanPackageLocked, unless those directories existed before we even tried to
             // install.
             deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
                     dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
                             res.removedInfo, true);
         }

     } catch (PackageManagerException e) {
         res.setError("Package couldn't be installed in " + pkg.codePath, e);
     }
}

  查看updateSettingsLI()源码,对mPackages的同步处理中,调用了Setting的writeLPr()方法。

private void updateSettingsLI(PackageParser.Package newPackage, 
        String installerPackageName,
        int[] allUsers, boolean[] perUserInstalled,
        PackageInstalledInfo res) {
      String pkgName = newPackage.packageName;
      synchronized (mPackages) {
          //write settings. the installStatus will be incomplete at this stage.
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值