Android Q应用安装流程分析

1、adb install xxx

会响应到adb_commandline,本文重点讲解单个app安装install_app

// system/core/adb/client/commandline.cpp
int adb_commandline(int argc, const char** argv) {
    ...
    } else if (!strcmp(argv[0], "install")) {
        if (argc < 2) error_exit("install requires an argument");
        return install_app(argc, argv); // 安装单个应用,本文重点讲解
    } else if (!strcmp(argv[0], "install-multiple")) {
        if (argc < 2) error_exit("install-multiple requires an argument");
        return install_multiple_app(argc, argv);
    } else if (!strcmp(argv[0], "install-multi-package")) {
        if (argc < 3) error_exit("install-multi-package requires an argument");
        return install_multi_package(argc, argv);
    } else if (!strcmp(argv[0], "uninstall")) {
        if (argc < 2) error_exit("uninstall requires an argument");
        return uninstall_app(argc, argv);
    }
    ...
}
// system/core/adb/client/adb_install.cpp
int install_app(int argc, const char** argv) {
    ...
    return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
                                      use_fastdeploy, use_localagent);
    ...
}
static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
                              bool use_localagent) {
    ...
    result = pm_command(argc, argv);
    ...
}
static int pm_command(int argc, const char** argv) {
    std::string cmd = "pm";

    while (argc-- > 0) {
        cmd += " " + escape_arg(*argv++);
    }
    return send_shell_command(cmd);
}
// system/core/adb/client/commandline.cpp
int send_shell_command(const std::string& command, bool disable_shell_protocol,
                       StandardStreamsCallbackInterface* callback) {
    // 这块较为繁琐,原理是是通过socket传递到frameworks/native/cmds/cmd/cmd.cpp中
}
// frameworks/native/cmds/cmd/cmd.cpp
int cmdMain(const std::vector& argv, TextOutput& outputLog, TextOutput& errorLog,
            int in, int out, int err, RunMode runMode) {
    ...
    String16 serviceName = String16(cmd.data(), cmd.size());
    for (int i = 1; i < argc; i++) {
        args.add(String16(argv[i].data(), argv[i].size()));
    }
    sp service = sm->checkService(serviceName);
    ...
    status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
    ...
}
// frameworks/base/core/java/android/os/Binder.java
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
            @Nullable FileDescriptor err,
            @NonNull String[] args, @Nullable ShellCallback callback,
            @NonNull ResultReceiver resultReceiver) throws RemoteException {
    // 这里会根据不同服务传递到不服务对应的onShellCommand接口中
    onShellCommand(in, out, err, args, callback, resultReceiver);
}
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ShellCallback callback,
            ResultReceiver resultReceiver) {
    (new PackageManagerShellCommand(this)).exec(
            this, in, out, err, args, callback, resultReceiver);
}
public int onCommand(String cmd) {
    ...
    case "install":
        return runInstall();
    ...
}
private int runInstall() throws RemoteException {
    ...
    // 创建session
    final int sessionId = doCreateSession(params.sessionParams,
        params.installerPackageName, params.userId);
    ...
    // 把apk信息写入到sessionID对应的session中
    if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
        false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
        return 1;
    }
    // 提交session,执行安装
    if (doCommitSession(sessionId, false /*logSuccess*/)
        != PackageInstaller.STATUS_SUCCESS) {
        return 1;
    }
    ...
}
private int doCommitSession(int sessionId, boolean logSuccess)
            throws RemoteException {
    ...
    session.commit(receiver.getIntentSender());
    ...
}
// frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
    ...
    mHandler.obtainMessage(MSG_COMMIT).sendToTarget();// handler到handleCommit
}
private void handleCommit() {
    ...
    commitNonStagedLocked(childSessions);
    ...
}
private void commitNonStagedLocked(List childSessions)
            throws PackageManagerException {
    ...
    mPm.installStage(committingSession);
    ...
}
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void installStage(ActiveInstallSession activeInstallSession) {
    ...
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    ...
    mHandler.sendMessage(msg); // handler到HandlerParams.startCopy
}

// InstallParams extends HandlerParams
// InstallParams单个应用安装
private abstract class HandlerParams {
    final void startCopy() {
        handleStartCopy(); // 最重要的工作就是计算应用安装的位置
        handleReturnCode();
    }
}
class InstallParams extends HandlerParams {
    void handleStartCopy() {
        ...
        final InstallArgs args = createInstallArgs(this);
        ...
    }
    void handleReturnCode() {
        ...
        // FileInstallArgs.copyApk
        //   FileInstallArgs.doCopyApk
        //     PackageManagerServiceUtils.copyPackage
        //       PackageParser.parsePackageLite
        //       copyFile(pkg.baseCodePath, targetDir, "base.apk");
        mRet = mArgs.copyApk();
        processPendingInstall(mArgs, mRet);
    }
}
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)));
    }
}
private void processInstallRequestsAsync(boolean success,
            List installRequests) {
    ...
    request.args.doPreInstall(request.installResult.returnCode); // 准备工作
    ...
    installPackagesTracedLI(installRequests);
    ...
    request.args.doPostInstall(...); // 清理工作
    ...
    restoreAndPostInstall(...); // 后续工作(比如发送应用变化相关的广播)
}
private void installPackagesTracedLI(List requests) {
    ...
    //  -> preparePackageLI
    //  -> scanPackageTracedLI
    //  -> reconcilePackagesLocked
    //  -> commitPackagesLocked
    //  -> executePostCommitSteps
    installPackagesLI(requests);// 具体安装过程
    ...
}

2、preparePackageLI

1、准备scanFlags

SCAN_NEW_INSTALL
SCAN_UPDATE_SIGNATURE
SCAN_INITIAL(已经初始化过, args.move != null)
SCAN_DONT_KILL_APP(不需要杀掉, (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0)
SCAN_AS_INSTANT_APP(instantApp)
SCAN_AS_FULL_APP(fullApp)
SCAN_AS_VIRTUAL_PRELOAD(虚拟预加载, virtualPreload)

2、instantApp不能安装在外置存储

if (instantApp && onExternal) throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);

3、解析Package

pkg = pp.parsePackage(tmpPackageFile, parseFlags);

4、instantApp校验

instantApp只能在android O及以上使用

5、重命名库

renameStaticSharedLibraryPackage
名字上添加版本号,方便多版本共存

6、替换安装检测

检测是否安装过(mOriginalPackages和非mOriginalPackages)
有父包禁止安装
检查targetSDK
禁止PERSISTENT 非 stage安装

 synchronized (mPackages) {
    // Check if installing already existing package
    ...
}

7、与老版本签名比对

PackageSetting ps = mSettings.mPackages.get(pkgName);
    if (ps != null) {
        if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
    }
    ...
}

8、权限处理

非系统应用移除PROTECTION_FLAG_INSTANT
替换安装有升级Key,验证升级Key(checkUpgradeKeySetLocked)
替换安装没有升级Key,匹配证书(checkCapability)

9、系统应用不支持instantApp和安装在外置存储

10、abi处理

move:更新primaryCpuAbi 和 secondaryCpuAbi
非Move:derivePackageAbi

11、覆盖安装

if (replace) {
    targetVolumeUuid = null;
    if (pkg.applicationInfo.isStaticSharedLibrary()) {
        // Static libs have a synthetic package name containing the version
        // and cannot be updated as an update would get a new package name,
        // unless this is the exact same version code which is useful for
        // development.
    ...

静态共享库禁止同版本升级
验证签名(checkUpgradeKeySetLocked、checkCapability)
升级限制验证(升级哈希匹配才能升级)
检查shared user id
禁止 instant app替换full app
更新后被移除的子包
系统包设置FLAG_UPDATED_SYSTEM_APP

12、新安装

检查系统是否已存在

3、scanPackageTracedLI

主要用于生成PackageSetting数据结构。
执行完scanPackageTrackLI之后Pms的两大核心数据结构都已经准备好了:

final ArrayMap mPackages = new ArrayMap<>()
mSettings.mPackages的PackageSetting

PackageParser.Package为静态数据,扫描完成后就不会发生变化。PackageSetting用于存储安装应用的动态数据,如权限授予情况等。PackageParser.Package由于是静态数据,扫描apk就可以获取。PackageSetting生成之后会被记录到文件中,以后每次系统启动都会重新加载。

4、reconcilePackagesLocked

生成PackageSetting和PackageParser.Package数据结构后,还需要对多个安装apk结果进行核对,这就是reconcilePackagesLocked函数。

1、复制现有包以便与传入包合并(combinedPackages.putAll(request.allPackages))
2、用传入包替换现有包(combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg))
3、根据版本号添加静态共享库(addSharedLibraryToPackageVersionMap)
4、删除非系统应用的现有包(mayDeletePackageLocked)
5、验证签名(checkUpgradeKeySetLocked、verifySignatures)

5、commitPackagesLocked

经过上述几个步骤,两个核心数据结构虽然已经生成,但是并没有添加到容器中去(PackageManagerService.mPackages 和 PackageManagerService.mSettings.mPackage), 所以该包里面的组件等还不能查询到,也不能启动。 所以需要commitPackagesLocked来进行提交, 提交之后该应用就算完整发布了。

1、覆盖安装

1、设置安装和更新时间(setInstallAndUpdateTime)
2、系统应用-移除现有包(removePackageLI)
3、系统应用-记录现有包需要删除的覆盖安装的应用
4、系统应用-处理子包
4、非系统应用-删除包(executeDeletePackageLIF)

2、commitReconciledScanResultLocked

1、shared user改变,移除old shared user
2、PackageSetting更新
3、更新共享库(executeSharedLibrariesUpdateLPr)
4、更新签名信息(pkgSetting.signatures.mSigningDetails)
5、采用另一个package的权限所有权(mSettings.mPermissions.transferPermissions)
6、更新AbiCodePath(mInstaller.rmdex)
7、commitPackageSettings

3、commitPackageSettings

1、更新静态共享库(commitSharedLibraryInfoLocked、updateSharedLibrariesLocked)
2、更新库时杀掉依赖程序(killApplication)
3、添加组件、权限组、权限(addAllComponents、addAllPermissionGroups、addAllPermissions)
4、更新mInstrumentation
5、更新mProtectedBroadcasts
6、撤销需要撤销的权限(revokeRuntimePermissionsIfGroupChanged)

6、executePostCommitSteps

1、准备APP数据(prepareAppDataAfterInstallLIF)
2、notifyPackageUpdated
3、prepareAppProfiles
4、编译布局资源(compileLayouts)
5、执行Dex优化(performDexOpt)

7、restoreAndPostInstall

1、备份恢复(restoreAtInstallForUser)
2、使用rollbackMnaager恢复数据(snapshotAndRestoreUserData)
3、安装成功(POST_INSTALL, 没有doRestore)

8、handlePackagePostInstall

1、发送移除广播(sendPackageRemovedBroadcasts)
2、设置白名单限制权限(setWhitelistedRestrictedPermissions)
3、运行时权限(grantRequestedRuntimePermissions、grantRuntimePermissionsGrantedToDisabledPackage)
4、ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REPLACED广播

你可能感兴趣的:(Android Q应用安装流程分析)