Android应用安装流程(AndroidU)

一:背景

    应用下载安装是用户很常用的场景之一,如果有两个同类型的应用A和B,功能、UI相差不多,但是A应用安装需要3s,B应用安装只需要1s,那么无疑B应用会更受用户欢迎。如何减少应用安装时间,那就必须要了解应用安装过程中需要做哪些事情,耗时点在哪里。

    那么应用安装过程中系统到底做了哪些事情呢,且看下文。

二:安装方式

    应用安装有4种方式

    1. 系统预置应用:包括系统应用和预置应用。在开机过程中完成安装,静默安装,没有安装界面,用户无法感知。

    2. 使用adb安装:adb install A.apk,静默安装,没有安装界面,如果安装失败会有详细的报错信息显示。

    3. 应用商店下载安装:静默安装,没有安装界面,下载完成后会自动安装。

    4. 用户点击存储里的apk安装包进行安装:有安装界面及安装进度显示,需要触发安装apk动作的应用有安装权限。

    下面将从第四种安装方式来剖析安装流程

三:PackageInstaller安装应用

    当用户点击存储里的apk安装包时,系统识别到这是一个apk,会启动PackageInstaller进程的InstallStart Activity来触发apk的安装流程

时序图如下所示

    3.1 InstallStart.onCreate

    InstallStart启动后,会根据传进来的intent判断是否是install类型的session,如果是则启动PackageInstallerActivity来显示安装界面。

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        //这里传入的action是android.content.pm.action.CONFIRM_INSTALL,所以isSessionInstall为true
        final boolean isSessionInstall =
                PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
                        || PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
        ...
        Intent nextActivity = new Intent(intent);
        ...
        //isSessionInstall为true,启动PackageInstallerActivity
        if (isSessionInstall) {
            nextActivity.setClass(this, PackageInstallerActivity.class);
        }
        ...
        if (nextActivity != null) {
            try {
                startActivity(nextActivity);
            } catch (SecurityException e) {
                ...
            }
        }
        finish();
    }

    3.2 PackageInstallerActivity.bindUi

    PackageInstallerActivity启动后,会先解析被安装应用的AndroidManifest,获取应用的安装名和icon等信息,保存在AppSinppet对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    protected void onCreate(Bundle icicle) {
        ...
        if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(action)) {
            final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
                    -1 /* defaultValue */);
            final SessionInfo info = mInstaller.getSessionInfo(sessionId);
            String resolvedPath = info != null ? info.getResolvedBaseApkPath() : null;
            ...
            //初始化mSessionId和packageSource
            mSessionId = sessionId;
            packageSource = Uri.fromFile(new File(resolvedPath));
            ...
        }
        ...
        final boolean wasSetUp = processAppSnippet(packageSource);
        ...
    }

    private boolean processAppSnippet(@NonNull Object source) {
        if (source instanceof Uri) {
            return processPackageUri((Uri) source);
        }
        ...
    }

    private boolean processPackageUri(final Uri packageUri) {
        ...
        switch (scheme) {
            case ContentResolver.SCHEME_FILE: {
                File sourceFile = new File(packageUri.getPath());
                //PackageUtil解析应用的AndroidManifest,获取应用的包名、版本号等信息
                mPkgInfo = PackageUtil.getPackageInfo(this, sourceFile,
                        PackageManager.GET_PERMISSIONS);
                ...
                //获取应用的安装名和icon,保存在AppSnippet对象中
                mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
            } break;
        }
    }

    protected void onResume() {
        ...
        if (mAppSnippet != null) {
            //初始化弹框UI
            bindUi();
            //检查是否有安装权限,如果有则初始化安装UI
            checkIfAllowedAndInitiateInstall();
        }
        ...
    }

3.3 PackageInstallerActivity.checkIfAllowedAndInitiateInstall

    如果安装应用的应用没有安装未知来源的权限,会启动提供用户开启允许安装来自未知应用的Dialog,用户点击Settings按钮,会注册UnknownSourcesListener的监听回调并启动系统-设置模块里面的Install unknown apps界面

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    private void checkIfAllowedAndInitiateInstall() {
        ...
        //检查应用是否有安装未知应用权限
        handleUnknownSources();
    }

    private void handleUnknownSources() {
        ...
        //获取应用的AppOps权限,默认是MODE_DEFAULT
        final int appOpMode = mAppOpsManager.noteOpNoThrow(...);
        switch (appOpMode) {
            case AppOpsManager.MODE_DEFAULT:
                mAppOpsManager.setMode(appOpStr, mOriginatingUid,
                        mOriginatingPackage, AppOpsManager.MODE_ERRORED);
            case AppOpsManager.MODE_ERRORED:
                showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);
                break;
            ...
        }
    }

    private void showDialogInner(int id) {
        ...
        //根据传进来的id,判断要创建哪种dialog
        DialogFragment newDialog = createDialog(id);
        ...
    }

    private void showDialogInner(int id) {
        ...
        //根据传进来的id,判断要创建哪种dialog
        DialogFragment newDialog = createDialog(id);
        ...
    }

    private DialogFragment createDialog(int id) {
        switch (id) {
            ...
            case DLG_EXTERNAL_SOURCE_BLOCKED:
                return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
            ...
        }
        ...
    }

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.ExternalSourcesBlockedDialog.java
    public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
        ...
        protected Dialog createDialog(@NonNull CharSequence argument) {
            ...
            try {
                ...
                return new AlertDialog.Builder(activity)
                        ...
                        .setPositiveButton(R.string.external_sources_settings,
                                (dialog, which) -> {
                                    ...
                                    try {
                                        //注册UnknownSourcesListener的监听回调
                                        activity.register(activity.new UnknownSourcesListener());
                                        //启动Settings里面的Install unknown apps界面,由用户选择是否要打开Allow from this source开关。开关打开后,会调用UnknownSourcesListener的onOpChanged回调函数
                                        activity.startActivityForResult(settingsIntent,
                                                REQUEST_TRUST_EXTERNAL_SOURCE);
                                    }
                                    ...
                                })
                        .setNegativeButton(R.string.cancel,
                                (dialog, which) -> activity.finish())
                        .create();
            }
            ...
        }
    }

3.4 PackageInstallerActivity.initiateInstall

    当用户在设置模块的允许安装未知来源界面点击允许时,PackageInstallerActivity会收到onOpChanged的回调,再次启动PackageInstallerActivity,初始化安装UI

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.UnknownSourcesListener.java
    private class UnknownSourcesListener implements AppOpsManager.OnOpChangedListener {

        @Override
        public void onOpChanged(String op, String packageName) {
            ...
            //解绑监听
            unregister(this);
            ...
            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                if (!isDestroyed()) {
                    //启动PackageInstallerActivity
                    startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
                }
            }, 500);
        }
    }

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    private void checkIfAllowedAndInitiateInstall() {
        if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
            //初始化安装UI
            initiateInstall();
        }
        ...
    }

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    private void initiateInstall() {
        ...
        startInstallConfirm();
    }

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    private void startInstallConfirm() {
        TextView viewToEnable;

        if (mAppInfo != null) {
            ...
        } else {
            // This is a new application with no permissions.
            viewToEnable = requireViewById(R.id.install_confirm_question);
        }

        viewToEnable.setVisibility(View.VISIBLE);

        mEnableOk = true;
        //设置mOk为可点击的状态
        mOk.setEnabled(true);
        mOk.setFilterTouchesWhenObscured(true);
    }

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    private void bindUi() {
        ...
        mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
                (ignored, ignored2) -> {
                    if (mOk.isEnabled()) {
                        if (mSessionId != -1) {
                            setActivityResult(RESULT_OK);
                            finish();
                        }
                        ...
                    }
                }, null);
        ...
    }

3.5 PackageInstallerSession.handleInstall

    当用户点击Install按钮后,安装界面的Dialog会消失,最终会调用到PackageInstallerSession的handleInstall函数来触发安装流程。

//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
    public void finish() {
        if (mSessionId != -1) {
            if (mActivityResultCode == Activity.RESULT_OK) {
                mInstaller.setPermissionsResult(mSessionId, true);
            }
            ...
        }
        ...
    }

//frameworks/base/core/java/android/content/pm/PackageInstaller.java
    public void setPermissionsResult(int sessionId, boolean accepted) {
        try {
            mInstaller.setPermissionsResult(sessionId, accepted);
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
    public void setPermissionsResult(int sessionId, boolean accepted) {
        //检查应用是否有INSTALL_PACKAGES权限
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);

        synchronized (mSessions) {
            PackageInstallerSession session = mSessions.get(sessionId);
            if (session != null) {
                session.setPermissionsResult(accepted);
            }
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    void setPermissionsResult(boolean accepted) {
        ...
        if (accepted) {
            ...
            //isCommitted()为true,这里会发送MSG_INSTALL类型的message
            root.mHandler.obtainMessage(
                    isCommitted() ? MSG_INSTALL : MSG_PRE_APPROVAL_REQUEST).sendToTarget();
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                ...
                case MSG_INSTALL:
                    //触发安装流程
                    handleInstall();
                    break;
                ...
            }
            ...
        }
    };

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void handleInstall() {
        ...
        //校验
        verify();
    }

3.6 PackageInstallerSession.verify

安装第一步:校验。

  1. 解析apk,并把apk信息保存在PackageLite对象中
  2. 计算安装进度条
  3. 提取native lib库
  4. 检查是新安装还是升级安装还是降级安装
  5. 进行完整性验证
  6. 进行签名验证
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void verify() {
        try {
            List<PackageInstallerSession> children = getChildSessions();
            if (isMultiPackage()) {
                ...
            } else {
                //准备继承的文件
                prepareInheritedFiles();
                //解析apk和native库
                parseApkAndExtractNativeLibraries();
            }
            verifyNonStaged();
        } catch (PackageManagerException e) {
            ...
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void prepareInheritedFiles() throws PackageManagerException {
        //新安装的应用,mode不等于MODE_INHERIT_EXISTING,会直接return
        if (isApexSession() || params.mode != SessionParams.MODE_INHERIT_EXISTING) {
            return;
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void parseApkAndExtractNativeLibraries() throws PackageManagerException {
        synchronized (mLock) {
            ...
            //
            if (!isApexSession()) {
                ...
                //解析apk,并把apk信息保存在PackageLite对象中返回
                result = getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
            }
            ...
            if (result != null) {
                ...
                if (!isApexSession()) {
                    synchronized (mProgressLock) {
                        mInternalProgress = 0.5f;
                        //计算安装进度条
                        computeProgressLocked(true);
                    }
                    //提取native lib库
                    extractNativeLibraries(
                            mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
                }
            }
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void verifyNonStaged()
            throws PackageManagerException {
        synchronized (mLock) {
            markStageDirInUseLocked();
        }
        mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
            mHandler.post(() -> {
                if (dispatchPendingAbandonCallback()) {
                    // No need to continue if abandoned
                    return;
                }
                Log.d(TAG, "verifyNonStaged error : " + error);
                if (error == INSTALL_SUCCEEDED) {
                    onVerificationComplete();
                } else {
                    onSessionVerificationFailure(error, msg);
                }
            });
        });
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
    public void verify(PackageInstallerSession session, Callback callback) {
        mHandler.post(() -> {
            try {
                ...
                if (session.isMultiPackage()) {
                    ...
                } else {
                    //检查是否允许更新Apex
                    checkApexUpdateAllowed(session);
                    //检查是否是重新启动的Apex会话
                    checkRebootlessApex(session);
                    //检查Apex签名
                    checkApexSignature(session);
                }
                //校验apk
                verifyAPK(session, callback);
            } catch (PackageManagerException e) {
                ...
            }
        });
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
    private void verifyAPK(PackageInstallerSession session, Callback callback)
            throws PackageManagerException {
        ...
        verifyingSession.verifyStage();
    }

//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
    public void verifyStage() {
        ...
        mPm.mHandler.post(this::start);
    }

//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
    private void start() {
        ...
        //开始验证
        handleStartVerify();
        //返回结果
        handleReturnCode();
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
    public void handleStartVerify() {
        ...
        //校验是升级还是降级
        Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
                pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
        ...
        if (!mOriginInfo.mExisting) {
            if (!isApex()) {
                //完整性和签名验证
                sendApkVerificationRequest(pkgLite);
            }
            if ((mInstallFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
                //防回滚验证
                sendEnableRollbackRequest();
            }
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
    private void sendApkVerificationRequest(PackageInfoLite pkgLite) {
        ...
        //进行完整性验证,验证metadata、versioncode、签名等信息是否完整
        sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
        //进行签名验证
        sendPackageVerificationRequest(
                verificationId, pkgLite, verificationState);
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private void onVerificationComplete() {
        ...
        install();
    }

3.7 InstallingSession.copyApk

    安装第二步:拷贝

  1. 拷贝codeFile
  2. 拷贝native lib库
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private CompletableFuture<Void> install() {
        List<CompletableFuture<InstallResult>> futures = installNonStaged();
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
    private List<CompletableFuture<InstallResult>> installNonStaged() {
        try {
            ...
            //创建安装会话
            final InstallingSession installingSession = createInstallingSession(future);
            if (isMultiPackage()) {
                ...
            } else if (installingSession != null) {
                installingSession.installStage();
            }
            ...
        } catch (PackageManagerException e) {
            ...
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    public void installStage() {
        ...
        mPm.mHandler.post(this::start);
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void start() {
        ...
        InstallRequest installRequest = new InstallRequest(this);
        handleStartCopy(installRequest);
        handleReturnCode(installRequest);
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void handleStartCopy(InstallRequest request) {
        ...
        if (!mOriginInfo.mStaged && pkgLite.recommendedInstallLocation
                == InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
            //如果剩余存储空间很少,不够安装使用,则做一次清理cache的动作
            pkgLite.recommendedInstallLocation = mPm.freeCacheForInstallation(
                    pkgLite.recommendedInstallLocation, mPackageLite,
                    mOriginInfo.mResolvedPath, mPackageAbiOverride, mInstallFlags);
        }
        //更新mInstallFlags
        mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
                pkgLite.installLocation);
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void handleReturnCode(InstallRequest installRequest) {
        processPendingInstall(installRequest);
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void processPendingInstall(InstallRequest installRequest) {
        if (mRet == PackageManager.INSTALL_SUCCEEDED) {
            //拷贝apk
            mRet = copyApk(installRequest);
        }
        ...
        if (mParentInstallingSession != null) {
            ...
        } else {
            //异步进行安装工作
            mPm.mHandler.post(() -> processInstallRequests(
                    mRet == PackageManager.INSTALL_SUCCEEDED /* success */,
                    Collections.singletonList(installRequest)));
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private int copyApk(InstallRequest request) {
        if (mMoveInfo == null) {
            return copyApkForFileInstall(request);
        } else {
            ...
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private int copyApkForFileInstall(InstallRequest request) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
        try {
            ...
            //拷贝codeFile
            ret = PackageManagerServiceUtils.copyPackage(
                    mOriginInfo.mFile.getAbsolutePath(), request.getCodeFile());
            ...
            try {
                //拷贝native lib库
                ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                        request.getAbiOverride(), isIncremental);
                ...
            }
            ...
        }
        ...
    }

3.8 AppDataHelper.prepareAppDataPostCommitLIF

    安装第三步:安装应用

  1. 解析apk,把结果保存在ParsedPakcage中
  2. 将包重命名为最终存放位置
  3. 冻结进程
  4. 判断包是否有效
  5. 检索包名判断是否合法
  6. 调用Installd进程进行安装工作
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
        ...
        processApkInstallRequests(success, installRequests);
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
    private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
        if (!success) {
            ...
        } else {
            mInstallPackageHelper.installPackagesTraced(installRequests);

            for (InstallRequest request : installRequests) {
                request.onInstallCompleted();
                doPostInstall(request);
            }
        }
        for (InstallRequest request : installRequests) {
            mInstallPackageHelper.restoreAndPostInstall(request);
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    void installPackagesTraced(List<InstallRequest> requests) {
        synchronized (mPm.mInstallLock) {
            try {
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
                installPackagesLI(requests);
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private void installPackagesLI(List<InstallRequest> requests) {
        ...
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    ...
                    preparePackageLI(request);
                } catch (PrepareFailure prepareFailure) {
                    ...
                } finally {
                    ...
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                ...
                try {
                    request.onScanStarted();
                    final ScanResult scanResult = scanPackageTracedLI(...);
                }
            }
            ...
            synchronized (mPm.mLock) {
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
                    //对多个apk进行一致性处理
                    reconciledPackages = ReconcilePackageUtils.reconcilePackages(...);
                } catch (ReconcileFailure e) {
                    ...
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
                    commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
                    success = true;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
            }
            executePostCommitStepsLIF(reconciledPackages);
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private void preparePackageLI(InstallRequest request) throws PrepareFailure {
        ...
        //解析apk,主要是解析apk的AndroidManifest.xml,并把结果保存在ParsedPackage中
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
        final ParsedPackage parsedPackage;
        try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
            parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
            AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
        } catch (PackageManagerException e) {
            ...
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        ...
        //如果有静态共享库,则重命名静态共享库的名字,拼接上应用包名
        if (parsedPackage.isStaticSharedLibrary()) {
            // Static shared libraries have synthetic package names
            PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
        }
        ...
        synchronized (mPm.mLock) {
            //如果是安装已有应用,进行sdk和persistent判断
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
                ...
            }
            //从现有PackageSetting列表中尝试通过包名获取PackageSetting,安装新应用时,ps为空
            PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
            PackageSetting signatureCheckPs = ps;
            ...
            //检查申明权限的合法性,权限是否已经被其他应用申明
            final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
            for (int groupNum = 0; groupNum < numGroups; groupNum++) {
                ...
            }
            ...
            //在PermissionManagerService进行权限兼容性的检查
            final int n = ArrayUtils.size(parsedPackage.getPermissions());
            for (int i = n - 1; i >= 0; i--) {
                ...
            }
            ...
        }
        ...
        if (!isApex) {
            //将包重命名为最终存放位置
            doRenameLI(request, parsedPackage);
            ...
        } else {
            ...
        }
        //应用安装期间,冻结进程
        final PackageFreezer freezer =
                freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags,
                        "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED);
        ...
        try {
            ...
            //更新信息到InstallRequest
            request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
                    oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
                    ps, disabledPs);
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private ScanResult scanPackageTracedLI(...) throws PackageManagerException {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
        try {
            return scanPackageNewLI(...);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private ScanResult scanPackageNewLI(...)
            throws PackageManagerException {
        ...
        synchronized (mPm.mLock) {
            //判断包是否是有效的
            assertPackageIsValid(parsedPackage, parseFlags, newScanFlags);
            final ScanRequest request = new ScanRequest(...);
            //检索包名,判断合法性
            return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest,
                    currentTime);
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages,
            @NonNull int[] allUsers) {
        for (ReconciledPackage reconciledPkg : reconciledPackages) {
            ...
            //非第一次安装
            if (installRequest.isInstallReplace()) {...}
            ...
            //更新应用信息到PackageSetting中
            AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers);
            //更新应用信息到PMS.Settings中
            updateSettingsLI(pkg, allUsers, installRequest);
            ...
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
        for (ReconciledPackage reconciledPkg : reconciledPackages) {
            ...
            //安装应用
            mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
            ...
    }

//frameworks/base/services/core/java/com/android/server/pm/AppDataHelper.java
    public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
        ...
        for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
            final int flags;
            //判断安装路径
            if (StorageManager.isUserKeyUnlocked(user.id)
                    && smInternal.isCeStoragePrepared(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)) {
                //准备应用数据
                prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
                    ...
                });
            }
        }
        //以阻塞方式执行此批收集的所有待处理操作
        executeBatchLI(batch);
    }

3.9 ArtManagerLocal.dexoptPackage

    安装第四步:dex优化

调用AndroidRuntime进程dex优化工作

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
        for (ReconciledPackage reconciledPkg : reconciledPackages) {
            ...
            //安装应用
            mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
            ...
            //判断是否需要做dex优化
            final boolean performDexopt =
                    (!instantApp || android.provider.Settings.Global.getInt(
                            mContext.getContentResolver(),
                            android.provider.Settings.Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                            && !pkg.isDebuggable()
                            && (!onIncremental)
                            && dexoptOptions.isCompilationEnabled()
                            && !isApex;
            //需要做dex优化
            if (performDexopt) {
                ...
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
                ...
                //使用AndroidRuntime服务
                if (useArtService()) {
                    PackageManagerLocal packageManagerLocal =
                            LocalManagerRegistry.getManager(PackageManagerLocal.class);
                    try (PackageManagerLocal.FilteredSnapshot snapshot =
                                    packageManagerLocal.withFilteredSnapshot()) {
                        DexoptParams params =
                                dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
                        //在ART里做dex优化
                        DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
                                snapshot, packageName, params);
                        installRequest.onDexoptFinished(dexOptResult);
                    }
                } else {
                    ...
                }
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            ...
    }

3.10 PackageManagerService.finishPackageInstall

应用安装完成后,会发送ACTION_PACKAGE_ADDED/ACTION_PACKAGE_REPLACED/ACTION_PACKAGE_CHANGED广播,并触发PackageInstallObserver的onPackageInstalled函数回调

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    public void restoreAndPostInstall(InstallRequest request) {
        ...
        if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED && doRestore) {
            //解冻进程
            request.closeFreezer();
            //对给定的Request进行BackupManager还原
            doRestore = performBackupManagerRestore(userId, token, request);
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) {
        ...
        IBackupManager iBackupManager = mInjector.getIBackupManager();
        if (iBackupManager != null) {
            ...
            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
            try {
                if (iBackupManager.isUserReadyForBackup(userId)) {
                    iBackupManager.restoreAtInstallForUser(
                            userId, request.getPkg().getPackageName(), token);
                } else {
                    ...
                }
            }
            ...
        }
        ...
    }

//frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
    public void restoreAtInstallForUser(int userId, String packageName, int token)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            restoreAtInstall(userId, packageName, token);
        }
    }

//frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
    public void restoreAtInstall(@UserIdInt int userId, String packageName, int token) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "restoreAtInstall()");

        if (userBackupManagerService != null) {
            userBackupManagerService.restoreAtInstall(packageName, token);
        }
    }

//frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
    public void restoreAtInstall(String packageName, int token) {
        ...
        boolean skip = false;
        //这里获取到的restoreSet值是0
        long restoreSet = getAvailableRestoreToken(packageName);
        ...
        if (restoreSet == 0) {
            skip = true;
        }
        ...
        if (skip) {
            ...
            try {
                mPackageManagerBinder.finishPackageInstall(token, false);
            } catch (RemoteException e) { /* can't happen */ }
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    void finishPackageInstall(int token, boolean didLaunch) {
        ...
        final Message msg = mHandler.obtainMessage(PackageManagerService.POST_INSTALL, token,
                didLaunch ? 1 : 0);
        mHandler.sendMessage(msg);
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageHandler.java
    void doHandleMessage(Message msg) {
        switch (msg.what) {
            case POST_INSTALL: {
                ...
                request.closeFreezer();
                request.runPostInstallRunnable();
                if (!request.isInstallExistingForUser()) {
                    mInstallPackageHelper.handlePackagePostInstall(request, didRestore);
                }
                ...
            } break;
        }
    }

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
    void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) {
        ...
        final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
        ...
        if (succeeded) {
            //没有静态库
            if (request.getPkg().getStaticSharedLibraryName() == null) {
                ...
            } else if (!ArrayUtils.isEmpty(request.getLibraryConsumers())) {//有静态库
                ...
                for (int i = 0; i < request.getLibraryConsumers().size(); i++) {
                    //发送package changed广播
                    mPm.sendPackageChangedBroadcast(...);
                }
            }
        ...
        ...
        final boolean deferInstallObserver = succeeded && update;
        if (deferInstallObserver) {
            ...
        } else {
            //触发安装完成的回调
            mPm.notifyInstallObserver(request);
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    void sendPackageChangedBroadcast(...) {
        ...
        mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast(
                packageName, dontKillApp, componentNames, packageUid, reason, userIds,
                instantUserIds, broadcastAllowList));
    }

//frameworks/base/services/core/java/com/android/server/pm/BroadcastHelper.java
    public void sendPackageChangedBroadcast(...) {
        ...
        sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
                userIds, instantUserIds, broadcastAllowList, null /* filterExtrasForReceiver */,
                null /* bOptions */);
    }

//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    void notifyInstallObserver(InstallRequest request) {
        if (request.getObserver() != null) {
            try {
                Bundle extras = extrasForInstallResult(request);
                //触发安装完成的回调
                request.getObserver().onPackageInstalled(request.getName(),
                        request.getReturnCode(), request.getReturnMsg(), extras);
            } catch (RemoteException e) {
                Slog.i(TAG, "Observer no longer exists.");
            }
        }
    }

四:小结

4.1 如何在日志中查看应用安装各个阶段的耗时

    把PMS里面的DEBUG_INSTALL改为true,日志中搜索PackageManager关键字,即可看到应用安装流程耗时

4.2 如何优化应用安装速度

  • 减少应用安装包大小,减少应用拷贝时间:去掉不必要的资源文件;如需必要不引用三方库,避免重复库的引用;动态加载.so文件;小图片使用矢量图等
  • 提前做dex优化:适用于系统预置应用,在编译时做dex优化,在应用安装时节省dex优化时间
  • 对Installd/dex2oat绑大核:原理相同,绑大核可以使Installd和dex2oat执行更快,节省安装时间。但是绑大核可能会出现抢占前台进程的CPU大核的使用,造成前台进程卡顿等现象,需要做完整评估、测试后再决定是否上此方案

4.3 如何监听应用是否安装成功以及何时安装成功

    可以通过PackageInstallObserver来监听安装是否成功以及何时安装成功。也可通过接收ACTION_PACKAGE_ADDED/ACTION_PACKAGE_REPLACED/ACTION_PACKAGE_CHANGED等系统广播来实现此功能,不过广播实时性较差。

        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
            @Override
            public void onUserActionRequired(Intent intent) {
                throw new IllegalStateException();
            }

            @Override
            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                    Bundle extras) {
                if (returnCode == INSTALL_SUCCEEDED) {
                    future.complete(new InstallResult(PackageInstallerSession.this, extras));
                } else {
                    future.completeExceptionally(new PackageManagerException(returnCode, msg));
                }
            }
        };

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值