tsx81429 发表于 2024-12-16 05:21:49

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对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了
https://i-blog.csdnimg.cn/direct/2cad2afd0c194d1a8a45fc77860a18dc.png
//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界面
https://i-blog.csdnimg.cn/direct/ef8104523ce641cfa8ca35d9d92ee26c.png
https://i-blog.csdnimg.cn/direct/a271260c7f4e47cfa388b6757e004df3.png
//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
https://i-blog.csdnimg.cn/direct/e3acfef9fb184682bc9fa0b696059fa5.png
//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函数来触发安装流程。
https://i-blog.csdnimg.cn/direct/48f34a308edd4354adaafa14b0624d9b.png
//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

安装第一步:校验。

[*]解析apk,并把apk信息生存在PackageLite对象中
[*]盘算安装进度条
[*]提取native lib库
[*]检查是新安装还是升级安装还是降级安装
[*]进行完备性验证
[*]进行签名验证
//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

    安装第二步:拷贝

[*]拷贝codeFile
[*]拷贝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

    安装第三步:安装应用

[*]解析apk,把结果生存在ParsedPakcage中
[*]将包重定名为终极存放位置
[*]冻结进程
[*]判定包是否有用
[*]检索包名判定是否合法
[*]调用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));
                }
            }
      };

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android应用安装流程(AndroidU)