❤️Android 从源码解读 Apk 的安装过程 ❤️(下)

简介: prepareAppDataLeafLIF()Installer流程图相关推荐Android Gradle 详解Android apk 包体积优化

InstallParams


       接下来咱们看看 InstallParams 中 的 注释2 processPendingInstall(mArgs, mRet); 也就是装载部分。


    class InstallParams extends HandlerParams {
        ...
        @Override
        void handleReturnCode() {
            if (mVerificationCompleted
                    && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
                ...
                if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                    //注释1
                    mRet = mArgs.copyApk();
                }                
                //注释2
                processPendingInstall(mArgs, mRet);
            }
        }
    }
    }


processPendingInstall()


       装载部分


    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        //分包
        if (args.mMultiPackageInstallParams != null) {
            args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
        } else {
            //
            PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
            //异步操作,因为包安装可能需要一段时间。
            processInstallRequestsAsync(
                    res.returnCode == PackageManager.INSTALL_SUCCEEDED,
                    Collections.singletonList(new InstallRequest(args, res)));
        }
    }


processInstallRequestsAsync()


    private void processInstallRequestsAsync(boolean success,
            List<InstallRequest> installRequests) {
        mHandler.post(() -> {
            if (success) {
                for (InstallRequest request : installRequests) {
                     // 预安装操作,主要是检查安装包的状态,确保安装环境正常,如果安装环境有问题会清理拷贝文件
                    request.args.doPreInstall(request.installResult.returnCode);
                }
                synchronized (mInstallLock) {
                    //真正的安装阶段
                    installPackagesTracedLI(installRequests);
                }
                for (InstallRequest request : installRequests) {
                    request.args.doPostInstall(
                            request.installResult.returnCode, request.installResult.uid);
                }
            }
            for (InstallRequest request : installRequests) {
                restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                        new PostInstallData(request.args, request.installResult, null));
            }
        });
    }


installPackagesTracedLI()


1.    @GuardedBy({"mInstallLock", "mLock"})
    private void installPackagesTracedLI(List<InstallRequest> requests) {
        try {
            //添加跟踪 Trace。
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
            //调用 installPackageLI 方法进行安装。咱们接着看
            installPackagesLI(requests);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }


installPackagesLI()

    @GuardedBy("mInstallLock")
    private void installPackagesLI(List<InstallRequest> requests) {
        ...
        boolean success = false;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                final PrepareResult prepareResult;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    //注释1
                    //成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
                    prepareResult =
                            preparePackageLI(request.args, request.installResult);
                } catch (PrepareFailure prepareFailure) {
                    ...
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                ...
            }
        }
    }


  注释1:preparePackageLI() 包含内容过多咱们开始逐步讲解。


preparePackageLI()


    @GuardedBy("mInstallLock")
    private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
            throws PrepareFailure {
        final int installFlags = args.installFlags;
        final File tmpPackageFile = new File(args.getCodePath());
        final boolean onExternal = args.volumeUuid != null;
        final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
        final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
        final boolean virtualPreload =
                ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
        @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
        ...
        ParsedPackage parsedPackage;
        //PackageParser2:PackageParser 的 v2 用于在服务中启动解析时使用,并且必须包含服务包含的状态。
        try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
                mPackageParserCallback)) {
            // 注释1:pp.parsePackage()新包解析
            parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
            AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
        } catch (PackageParserException e) {
            throw new PrepareFailure("Failed parse during installPackageLI", e);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        ...
        try {
            // 要么使用我们得到的,要么直接从APK解析
            if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
                parsedPackage.setSigningDetails(args.signingDetails);
            } else {
                parsedPackage.setSigningDetails(
                        ParsingPackageUtils.getSigningDetails(parsedPackage, false /* skipVerify */));
            }
        } catch (PackageParserException e) {
            throw new PrepareFailure("Failed collect during installPackageLI", e);
        }
        //未使用v2签名
        if (instantApp && parsedPackage.getSigningDetails().signatureSchemeVersion
                < SignatureSchemeVersion.SIGNING_BLOCK_V2) {
            ...
        }
        boolean systemApp = false;
        boolean replace = false;
        synchronized (mLock) {
            // 检查是否已安装现有软件包
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            ...
              }
            PackageSetting ps = mSettings.mPackages.get(pkgName);
            if (ps != null) {
                if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
                // 将签名与最新库版本的包设置进行比较。
                PackageSetting signatureCheckPs = ps;
                if (parsedPackage.isStaticSharedLibrary()) {
                    ...
                }
                //注释2:快速校验安装包签名
                final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
                    if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                                + parsedPackage.getPackageName() + " upgrade keys do not match the "
                                + "previously installed version");
                    }
                } else {
                    ...
                }
                if (ps.pkg != null) {
                    systemApp = ps.pkg.isSystem();
                }
                res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
            }
            // 注释3:设置相关权限,生成、移植权限 
            int N = ArrayUtils.size(parsedPackage.getPermissions());
            for (int i = N - 1; i >= 0; i--) {
                final ParsedPermission perm = parsedPackage.getPermissions().get(i);
                final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName());
                ...
            }
        }
        if (args.move != null) {
            // 我们进行了就地移动,因此 dex 已准备就绪
            ...
        } else {
            // 启用 SCAN_NO_DEX 标志以在稍后阶段跳过 dexopt
            scanFlags |= SCAN_NO_DEX;
            try {
                final boolean extractNativeLibs = !AndroidPackageUtils.isLibrary(parsedPackage);
                PackageSetting pkgSetting;
                synchronized (mLock) {
                    pkgSetting = mSettings.getPackageLPr(pkgName);
                }
                // 注释4:生成安装包Abi(Application binary interface,应用二进制接口)
                String abiOverride =
                        (pkgSetting == null || TextUtils.isEmpty(pkgSetting.cpuAbiOverrideString)
                        ? args.abiOverride : pkgSetting.cpuAbiOverrideString);
                boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
                        && pkgSetting.getPkgState().isUpdatedSystemApp();
                AndroidPackage oldPackage = mPackages.get(pkgName);
                boolean isUpdatedSystemAppInferred = oldPackage != null && oldPackage.isSystem();
                final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
                        derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage,
                        isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
                        abiOverride, extractNativeLibs);
                derivedAbi.first.applyTo(parsedPackage);
                derivedAbi.second.applyTo(parsedPackage);
            } catch (PackageManagerException pme) {
                Slog.e(TAG, "Error deriving application ABI", pme);
                throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
                        "Error deriving application ABI");
            }
        }
        //注释5:冻结 安装包
        final PackageFreezer freezer =
                freezePackageForInstall(pkgName, installFlags, "installPackageLI");
        boolean shouldCloseFreezerBeforeReturn = true;
        try {
            final AndroidPackage existingPackage;
            String renamedPackage = null;
            boolean sysPkg = false;
            int targetScanFlags = scanFlags;
            int targetParseFlags = parseFlags;
            final PackageSetting ps;
            final PackageSetting disabledPs;
            if (replace) {
                //更新包
                ...
            } else { 
                // 新包安装
                ...
            }
            // 解冻 安装包
            shouldCloseFreezerBeforeReturn = false;
            //返回成功准备好的安装包所需的数据集。
            return new PrepareResult(replace, targetScanFlags, targetParseFlags,
                    existingPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
                    ps, disabledPs);
        } finally {
            res.freezer = freezer;
            if (shouldCloseFreezerBeforeReturn) {
                freezer.close();
            }
        }
    }


咱再回来看 installPackagesLI()


installPackagesLI()


    @GuardedBy("mInstallLock")
    private void installPackagesLI(List<InstallRequest> requests) {
        ...
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                final PrepareResult prepareResult;
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    //注释1
                    //成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
                    prepareResult =
                            preparePackageLI(request.args, request.installResult);
                ...
                try {
                    //扫描包并返回新解析的包。
                    //出现错误时返回null。
                    final ScanResult result = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user, request.args.abiOverride);
                    ...
                } catch (PackageManagerException e) {
                    request.installResult.setError("Scanning Failed.", e);
                    return;
                }
            }
            //包扫描结果和相关请求详细信息用于协调一个或多个包到系统的潜在添加。
            ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
                    installResults,
                    prepareResults,
                    mSharedLibraries,
                    Collections.unmodifiableMap(mPackages), versionInfos,
                    lastStaticSharedLibSettings);
            CommitRequest commitRequest = null;
            synchronized (mLock) {
                //ReconciledPackage:提交到内存中的数据结构和磁盘所需的所有数据的容器。
                //TODO:将此处包含的大部分数据移动到PackageSetting中进行提交。
                Map<String, ReconciledPackage> reconciledPackages;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
                    reconciledPackages = reconcilePackagesLocked(
                            reconcileRequest, mSettings.mKeySetManagerService);
                } catch (ReconcileFailure e) {
                    for (InstallRequest request : requests) {
                        request.installResult.setError("Reconciliation failed...", e);
                    }
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
                    commitRequest = new CommitRequest(reconciledPackages,
                            mUserManager.getUserIds());
                    commitPackagesLocked(commitRequest);
                    success = true;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
            }
            //注释2
            executePostCommitSteps(commitRequest);
        } finally {
            ...
        }
    }


注释2:这里有个 executePostCommitSteps() 方法,咱们一起来看看。


executePostCommitSteps()


1.    /**
     * 成功安装后,在提交完成并释放包锁后执行剩余步骤。 
     * 这些通常更昂贵或需要调用 installd,这通常会锁定 mLock。
     */
    private void executePostCommitSteps(CommitRequest commitRequest) {
        final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
        for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
            final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags
                            & PackageManagerService.SCAN_AS_INSTANT_APP) != 0);
            final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg;
            final String packageName = pkg.getPackageName();
            //注释1:安装并准备 APP 数据 
            prepareAppDataAfterInstallLIF(pkg);
            ...
            final boolean performDexopt =
                    (!instantApp || Global.getInt(mContext.getContentResolver(),
                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                    && !pkg.isDebuggable()
                    && (!onIncremental)
                    && dexoptOptions.isCompilationEnabled();
              //优化dex文件(实际为 dex2oat 操作,用来将 apk 中的 dex 文件转换为 oat 文件)
            if (performDexopt) {
                // Compile the layout resources.
                if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
                    mViewCompiler.compileLayouts(pkg);
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
                ScanResult result = reconciledPkg.scanResult;
                PackageSetting realPkgSetting = result.existingSettingCopied
                        ? result.request.pkgSetting : result.pkgSetting;
                if (realPkgSetting == null) {
                    realPkgSetting = reconciledPkg.pkgSetting;
                }
                // Unfortunately, the updated system app flag is only tracked on this PackageSetting
                boolean isUpdatedSystemApp = reconciledPkg.pkgSetting.getPkgState()
                        .isUpdatedSystemApp();
                realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
                mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
                        null /* instructionSets */,
                        getOrCreateCompilerPackageStats(pkg),
                        mDexManager.getPackageUseInfoOrDefault(packageName),
                        dexoptOptions);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            // Notify BackgroundDexOptService that the package has been changed.
            // If this is an update of a package which used to fail to compile,
            // BackgroundDexOptService will remove it from its denylist.
            // TODO: Layering violation
            BackgroundDexOptService.notifyPackageChanged(packageName);
            notifyPackageChangeObserversOnUpdate(reconciledPkg);
        }
        NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
    }


注释1:安装并准备 APP 数据。咱们来看看 prepareAppDataAfterInstallLIF(pkg);


prepareAppDataAfterInstallLIF()


    /**
     * 在安装或升级后立即为给定的应用程序准备应用程序数据。 
     * 此方法仅会小心地接触为其安装的用户,并强制 restorecon 处理任何 seinfo 更改。
     * 
     * 验证目录是否存在以及所有已安装的应用程序的所有权和标签是否正确。
     * 如果所有权不匹配,它将尝试通过擦除数据来恢复系统应用程序; 第三方应用程序数据保持不变。
     * 
     * 注意:为了避免死锁,不要在持有mLock锁的情况下调用这个方法
     */
    private void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.mPackages.get(pkg.getPackageName());
            mSettings.writeKernelMappingLPr(ps);
        }
        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
        for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
            final int flags;
            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            } else if (umInternal.isUserRunning(user.id)) {
                flags = StorageManager.FLAG_STORAGE_DE;
            } else {
                continue;
            }
            if (ps.getInstalled(user.id)) {
                // TODO:这里是我们关注的。咱们接着看
                prepareAppDataLIF(pkg, user.id, flags);
                if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                    // 在外部存储上准备应用程序数据;
                    // 目前这用于设置由安装程序正确创建的任何 OBB 目录。
                    int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
                    smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
                }
            }
        }
    }


prepareAppDataLIF()


1.    private void prepareAppDataLIF(AndroidPackage pkg, int userId, int flags) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        prepareAppDataLeafLIF(pkg, userId, flags);
    }


prepareAppDataLeafLIF()


    private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
        if (DEBUG_APP_DATA) {
            Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x"
                    + Integer.toHexString(flags));
        }
        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.mPackages.get(pkg.getPackageName());
        }
        final String volumeUuid = pkg.getVolumeUuid();
        final String packageName = pkg.getPackageName();
        final int appId = UserHandle.getAppId(pkg.getUid());
        String pkgSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
        Preconditions.checkNotNull(pkgSeInfo);
        final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : "");
        long ceDataInode = -1;
        try {
            ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                    appId, seInfo, pkg.getTargetSdkVersion());
        } catch (InstallerException e) {
            if (pkg.isSystem()) {
                logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
                        + ", but trying to recover: " + e);
                destroyAppDataLeafLIF(pkg, userId, flags);
                try {
                    //注释1: 最终调用 系统服务 Installer 安装
                    ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                            appId, seInfo, pkg.getTargetSdkVersion());
                    logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
                } catch (InstallerException e2) {
                    logCriticalInfo(Log.DEBUG, "Recovery failed!");
                }
            } else {
                Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e);
            }
        }
        if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) {
            mArtManagerService.prepareAppProfiles(pkg, userId,
                /* updateReferenceProfileContent= */ false);
        }
        if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
            // TODO: mark this structure as dirty so we persist it!
            synchronized (mLock) {
                if (ps != null) {
                    ps.setCeDataInode(ceDataInode, userId);
                }
            }
        }
        prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
    }


注释1:mInstaller


1.    // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
    // LOCK HELD.  Can be called with mInstallLock held.
    @GuardedBy("mInstallLock")
    final Installer mInstaller;


 咱们看看 Installer


Installer


public class Installer extends SystemService {
    ...
    private volatile IInstalld mInstalld;
    public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo, int targetSdkVersion) throws InstallerException {
        if (!checkBeforeRemote()) return -1;
        try {
            return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                    targetSdkVersion);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }  
    ...
}


调用 系统服务 Installer 安装


       至此整个 apk 的安装过程结束,实际上安装成功之后,还会发送一个 App 安装成功的广播 ACTION_PACKAGE_ADDED。手机桌面应用注册了这个广播,当接收到应用安装成功之后,就将 apk 的启动 icon 显示在桌面上。


流程图

微信图片_20220522230811.png


相关推荐


Android Gradle 详解


Android apk 包体积优化



相关文章
|
4天前
|
开发工具 Android开发 git
Windows下载android2.2完整源码(转)
Windows下载android2.2完整源码(转)
15 3
|
4天前
|
Java 开发工具 Android开发
如何在Eclipse中查看Android源码或者第三方组件包源码(转)
如何在Eclipse中查看Android源码或者第三方组件包源码(转)
13 4
|
4天前
|
存储 Java 开发工具
在Eclipse配置安装Android详细教程(新手)
在Eclipse配置安装Android详细教程(新手)
15 1
|
6天前
|
Java Android开发
Android12 双击power键启动相机源码解析
Android12 双击power键启动相机源码解析
20 0
|
6天前
|
机器学习/深度学习 Java Shell
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
26 0
|
3天前
|
Android开发
在android源码中编译ADW_Launcher
在android源码中编译ADW_Launcher
10 2
|
4天前
|
开发工具 Windows
Android4.0安装时需要更新软件包(原创)
Android4.0安装时需要更新软件包(原创)
14 3
|
6天前
|
Java Android开发
Android零基础入门(二)gradle的安装和详解
Android零基础入门(二)gradle的安装和详解
14 0
|
6天前
|
Oracle Java 关系型数据库
Android零基础入门(一)配置环境和安装Android Studio
Android零基础入门(一)配置环境和安装Android Studio
15 0
|
6天前
|
Android开发
Android 高通平台集成无源码apk示例
Android 高通平台集成无源码apk示例
15 0