Android应用安装流程(AndroidU)

打印 上一主题 下一主题

主题 907|帖子 907|积分 2721

一:背景

    应用下载安装是用户很常用的场景之一,如果有两个同范例的应用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来显示安装界面。
  1. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
  2.     protected void onCreate(@Nullable Bundle savedInstanceState) {
  3.         ...
  4.         //这里传入的action是android.content.pm.action.CONFIRM_INSTALL,所以isSessionInstall为true
  5.         final boolean isSessionInstall =
  6.                 PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
  7.                         || PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
  8.         ...
  9.         Intent nextActivity = new Intent(intent);
  10.         ...
  11.         //isSessionInstall为true,启动PackageInstallerActivity
  12.         if (isSessionInstall) {
  13.             nextActivity.setClass(this, PackageInstallerActivity.class);
  14.         }
  15.         ...
  16.         if (nextActivity != null) {
  17.             try {
  18.                 startActivity(nextActivity);
  19.             } catch (SecurityException e) {
  20.                 ...
  21.             }
  22.         }
  23.         finish();
  24.     }
复制代码
    3.2 PackageInstallerActivity.bindUi

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

  1. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  2.     protected void onCreate(Bundle icicle) {
  3.         ...
  4.         if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(action)) {
  5.             final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
  6.                     -1 /* defaultValue */);
  7.             final SessionInfo info = mInstaller.getSessionInfo(sessionId);
  8.             String resolvedPath = info != null ? info.getResolvedBaseApkPath() : null;
  9.             ...
  10.             //初始化mSessionId和packageSource
  11.             mSessionId = sessionId;
  12.             packageSource = Uri.fromFile(new File(resolvedPath));
  13.             ...
  14.         }
  15.         ...
  16.         final boolean wasSetUp = processAppSnippet(packageSource);
  17.         ...
  18.     }
  19.     private boolean processAppSnippet(@NonNull Object source) {
  20.         if (source instanceof Uri) {
  21.             return processPackageUri((Uri) source);
  22.         }
  23.         ...
  24.     }
  25.     private boolean processPackageUri(final Uri packageUri) {
  26.         ...
  27.         switch (scheme) {
  28.             case ContentResolver.SCHEME_FILE: {
  29.                 File sourceFile = new File(packageUri.getPath());
  30.                 //PackageUtil解析应用的AndroidManifest,获取应用的包名、版本号等信息
  31.                 mPkgInfo = PackageUtil.getPackageInfo(this, sourceFile,
  32.                         PackageManager.GET_PERMISSIONS);
  33.                 ...
  34.                 //获取应用的安装名和icon,保存在AppSnippet对象中
  35.                 mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
  36.             } break;
  37.         }
  38.     }
  39.     protected void onResume() {
  40.         ...
  41.         if (mAppSnippet != null) {
  42.             //初始化弹框UI
  43.             bindUi();
  44.             //检查是否有安装权限,如果有则初始化安装UI
  45.             checkIfAllowedAndInitiateInstall();
  46.         }
  47.         ...
  48.     }
复制代码
3.3 PackageInstallerActivity.checkIfAllowedAndInitiateInstall

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


  1. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  2.     private void checkIfAllowedAndInitiateInstall() {
  3.         ...
  4.         //检查应用是否有安装未知应用权限
  5.         handleUnknownSources();
  6.     }
  7.     private void handleUnknownSources() {
  8.         ...
  9.         //获取应用的AppOps权限,默认是MODE_DEFAULT
  10.         final int appOpMode = mAppOpsManager.noteOpNoThrow(...);
  11.         switch (appOpMode) {
  12.             case AppOpsManager.MODE_DEFAULT:
  13.                 mAppOpsManager.setMode(appOpStr, mOriginatingUid,
  14.                         mOriginatingPackage, AppOpsManager.MODE_ERRORED);
  15.             case AppOpsManager.MODE_ERRORED:
  16.                 showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);
  17.                 break;
  18.             ...
  19.         }
  20.     }
  21.     private void showDialogInner(int id) {
  22.         ...
  23.         //根据传进来的id,判断要创建哪种dialog
  24.         DialogFragment newDialog = createDialog(id);
  25.         ...
  26.     }
  27.     private void showDialogInner(int id) {
  28.         ...
  29.         //根据传进来的id,判断要创建哪种dialog
  30.         DialogFragment newDialog = createDialog(id);
  31.         ...
  32.     }
  33.     private DialogFragment createDialog(int id) {
  34.         switch (id) {
  35.             ...
  36.             case DLG_EXTERNAL_SOURCE_BLOCKED:
  37.                 return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
  38.             ...
  39.         }
  40.         ...
  41.     }
  42. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.ExternalSourcesBlockedDialog.java
  43.     public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
  44.         ...
  45.         protected Dialog createDialog(@NonNull CharSequence argument) {
  46.             ...
  47.             try {
  48.                 ...
  49.                 return new AlertDialog.Builder(activity)
  50.                         ...
  51.                         .setPositiveButton(R.string.external_sources_settings,
  52.                                 (dialog, which) -> {
  53.                                     ...
  54.                                     try {
  55.                                         //注册UnknownSourcesListener的监听回调
  56.                                         activity.register(activity.new UnknownSourcesListener());
  57.                                         //启动Settings里面的Install unknown apps界面,由用户选择是否要打开Allow from this source开关。开关打开后,会调用UnknownSourcesListener的onOpChanged回调函数
  58.                                         activity.startActivityForResult(settingsIntent,
  59.                                                 REQUEST_TRUST_EXTERNAL_SOURCE);
  60.                                     }
  61.                                     ...
  62.                                 })
  63.                         .setNegativeButton(R.string.cancel,
  64.                                 (dialog, which) -> activity.finish())
  65.                         .create();
  66.             }
  67.             ...
  68.         }
  69.     }
复制代码
3.4 PackageInstallerActivity.initiateInstall

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

  1. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.UnknownSourcesListener.java
  2.     private class UnknownSourcesListener implements AppOpsManager.OnOpChangedListener {
  3.         @Override
  4.         public void onOpChanged(String op, String packageName) {
  5.             ...
  6.             //解绑监听
  7.             unregister(this);
  8.             ...
  9.             new Handler(Looper.getMainLooper()).postDelayed(() -> {
  10.                 if (!isDestroyed()) {
  11.                     //启动PackageInstallerActivity
  12.                     startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
  13.                 }
  14.             }, 500);
  15.         }
  16.     }
  17. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  18.     private void checkIfAllowedAndInitiateInstall() {
  19.         if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
  20.             //初始化安装UI
  21.             initiateInstall();
  22.         }
  23.         ...
  24.     }
  25. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  26.     private void initiateInstall() {
  27.         ...
  28.         startInstallConfirm();
  29.     }
  30. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  31.     private void startInstallConfirm() {
  32.         TextView viewToEnable;
  33.         if (mAppInfo != null) {
  34.             ...
  35.         } else {
  36.             // This is a new application with no permissions.
  37.             viewToEnable = requireViewById(R.id.install_confirm_question);
  38.         }
  39.         viewToEnable.setVisibility(View.VISIBLE);
  40.         mEnableOk = true;
  41.         //设置mOk为可点击的状态
  42.         mOk.setEnabled(true);
  43.         mOk.setFilterTouchesWhenObscured(true);
  44.     }
  45. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  46.     private void bindUi() {
  47.         ...
  48.         mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
  49.                 (ignored, ignored2) -> {
  50.                     if (mOk.isEnabled()) {
  51.                         if (mSessionId != -1) {
  52.                             setActivityResult(RESULT_OK);
  53.                             finish();
  54.                         }
  55.                         ...
  56.                     }
  57.                 }, null);
  58.         ...
  59.     }
复制代码
3.5 PackageInstallerSession.handleInstall

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

  1. //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
  2.     public void finish() {
  3.         if (mSessionId != -1) {
  4.             if (mActivityResultCode == Activity.RESULT_OK) {
  5.                 mInstaller.setPermissionsResult(mSessionId, true);
  6.             }
  7.             ...
  8.         }
  9.         ...
  10.     }
  11. //frameworks/base/core/java/android/content/pm/PackageInstaller.java
  12.     public void setPermissionsResult(int sessionId, boolean accepted) {
  13.         try {
  14.             mInstaller.setPermissionsResult(sessionId, accepted);
  15.         }
  16.         ...
  17.     }
  18. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
  19.     public void setPermissionsResult(int sessionId, boolean accepted) {
  20.         //检查应用是否有INSTALL_PACKAGES权限
  21.         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
  22.         synchronized (mSessions) {
  23.             PackageInstallerSession session = mSessions.get(sessionId);
  24.             if (session != null) {
  25.                 session.setPermissionsResult(accepted);
  26.             }
  27.         }
  28.     }
  29. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  30.     void setPermissionsResult(boolean accepted) {
  31.         ...
  32.         if (accepted) {
  33.             ...
  34.             //isCommitted()为true,这里会发送MSG_INSTALL类型的message
  35.             root.mHandler.obtainMessage(
  36.                     isCommitted() ? MSG_INSTALL : MSG_PRE_APPROVAL_REQUEST).sendToTarget();
  37.         }
  38.         ...
  39.     }
  40. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  41.     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
  42.         @Override
  43.         public boolean handleMessage(Message msg) {
  44.             switch (msg.what) {
  45.                 ...
  46.                 case MSG_INSTALL:
  47.                     //触发安装流程
  48.                     handleInstall();
  49.                     break;
  50.                 ...
  51.             }
  52.             ...
  53.         }
  54.     };
  55. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  56.     private void handleInstall() {
  57.         ...
  58.         //校验
  59.         verify();
  60.     }
复制代码
3.6 PackageInstallerSession.verify

安装第一步:校验。

  • 解析apk,并把apk信息生存在PackageLite对象中
  • 盘算安装进度条
  • 提取native lib库
  • 检查是新安装还是升级安装还是降级安装
  • 进行完备性验证
  • 进行签名验证
  1. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  2.     private void verify() {
  3.         try {
  4.             List<PackageInstallerSession> children = getChildSessions();
  5.             if (isMultiPackage()) {
  6.                 ...
  7.             } else {
  8.                 //准备继承的文件
  9.                 prepareInheritedFiles();
  10.                 //解析apk和native库
  11.                 parseApkAndExtractNativeLibraries();
  12.             }
  13.             verifyNonStaged();
  14.         } catch (PackageManagerException e) {
  15.             ...
  16.         }
  17.     }
  18. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  19.     private void prepareInheritedFiles() throws PackageManagerException {
  20.         //新安装的应用,mode不等于MODE_INHERIT_EXISTING,会直接return
  21.         if (isApexSession() || params.mode != SessionParams.MODE_INHERIT_EXISTING) {
  22.             return;
  23.         }
  24.     }
  25. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  26.     private void parseApkAndExtractNativeLibraries() throws PackageManagerException {
  27.         synchronized (mLock) {
  28.             ...
  29.             //
  30.             if (!isApexSession()) {
  31.                 ...
  32.                 //解析apk,并把apk信息保存在PackageLite对象中返回
  33.                 result = getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
  34.             }
  35.             ...
  36.             if (result != null) {
  37.                 ...
  38.                 if (!isApexSession()) {
  39.                     synchronized (mProgressLock) {
  40.                         mInternalProgress = 0.5f;
  41.                         //计算安装进度条
  42.                         computeProgressLocked(true);
  43.                     }
  44.                     //提取native lib库
  45.                     extractNativeLibraries(
  46.                             mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
  47.                 }
  48.             }
  49.         }
  50.     }
  51. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  52.     private void verifyNonStaged()
  53.             throws PackageManagerException {
  54.         synchronized (mLock) {
  55.             markStageDirInUseLocked();
  56.         }
  57.         mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
  58.             mHandler.post(() -> {
  59.                 if (dispatchPendingAbandonCallback()) {
  60.                     // No need to continue if abandoned
  61.                     return;
  62.                 }
  63.                 Log.d(TAG, "verifyNonStaged error : " + error);
  64.                 if (error == INSTALL_SUCCEEDED) {
  65.                     onVerificationComplete();
  66.                 } else {
  67.                     onSessionVerificationFailure(error, msg);
  68.                 }
  69.             });
  70.         });
  71.     }
  72. //frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
  73.     public void verify(PackageInstallerSession session, Callback callback) {
  74.         mHandler.post(() -> {
  75.             try {
  76.                 ...
  77.                 if (session.isMultiPackage()) {
  78.                     ...
  79.                 } else {
  80.                     //检查是否允许更新Apex
  81.                     checkApexUpdateAllowed(session);
  82.                     //检查是否是重新启动的Apex会话
  83.                     checkRebootlessApex(session);
  84.                     //检查Apex签名
  85.                     checkApexSignature(session);
  86.                 }
  87.                 //校验apk
  88.                 verifyAPK(session, callback);
  89.             } catch (PackageManagerException e) {
  90.                 ...
  91.             }
  92.         });
  93.     }
  94. //frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
  95.     private void verifyAPK(PackageInstallerSession session, Callback callback)
  96.             throws PackageManagerException {
  97.         ...
  98.         verifyingSession.verifyStage();
  99.     }
  100. //frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
  101.     public void verifyStage() {
  102.         ...
  103.         mPm.mHandler.post(this::start);
  104.     }
  105. //frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
  106.     private void start() {
  107.         ...
  108.         //开始验证
  109.         handleStartVerify();
  110.         //返回结果
  111.         handleReturnCode();
  112.         ...
  113.     }
  114. //frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
  115.     public void handleStartVerify() {
  116.         ...
  117.         //校验是升级还是降级
  118.         Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
  119.                 pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
  120.         ...
  121.         if (!mOriginInfo.mExisting) {
  122.             if (!isApex()) {
  123.                 //完整性和签名验证
  124.                 sendApkVerificationRequest(pkgLite);
  125.             }
  126.             if ((mInstallFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
  127.                 //防回滚验证
  128.                 sendEnableRollbackRequest();
  129.             }
  130.         }
  131.     }
  132. //frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
  133.     private void sendApkVerificationRequest(PackageInfoLite pkgLite) {
  134.         ...
  135.         //进行完整性验证,验证metadata、versioncode、签名等信息是否完整
  136.         sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
  137.         //进行签名验证
  138.         sendPackageVerificationRequest(
  139.                 verificationId, pkgLite, verificationState);
  140.         ...
  141.     }
  142. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  143.     private void onVerificationComplete() {
  144.         ...
  145.         install();
  146.     }
复制代码
3.7 InstallingSession.copyApk

    安装第二步:拷贝

  • 拷贝codeFile
  • 拷贝native lib库
  1. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  2.     private CompletableFuture<Void> install() {
  3.         List<CompletableFuture<InstallResult>> futures = installNonStaged();
  4.         ...
  5.     }
  6. //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
  7.     private List<CompletableFuture<InstallResult>> installNonStaged() {
  8.         try {
  9.             ...
  10.             //创建安装会话
  11.             final InstallingSession installingSession = createInstallingSession(future);
  12.             if (isMultiPackage()) {
  13.                 ...
  14.             } else if (installingSession != null) {
  15.                 installingSession.installStage();
  16.             }
  17.             ...
  18.         } catch (PackageManagerException e) {
  19.             ...
  20.         }
  21.     }
  22. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  23.     public void installStage() {
  24.         ...
  25.         mPm.mHandler.post(this::start);
  26.     }
  27. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  28.     private void start() {
  29.         ...
  30.         InstallRequest installRequest = new InstallRequest(this);
  31.         handleStartCopy(installRequest);
  32.         handleReturnCode(installRequest);
  33.         ...
  34.     }
  35. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  36.     private void handleStartCopy(InstallRequest request) {
  37.         ...
  38.         if (!mOriginInfo.mStaged && pkgLite.recommendedInstallLocation
  39.                 == InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
  40.             //如果剩余存储空间很少,不够安装使用,则做一次清理cache的动作
  41.             pkgLite.recommendedInstallLocation = mPm.freeCacheForInstallation(
  42.                     pkgLite.recommendedInstallLocation, mPackageLite,
  43.                     mOriginInfo.mResolvedPath, mPackageAbiOverride, mInstallFlags);
  44.         }
  45.         //更新mInstallFlags
  46.         mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
  47.                 pkgLite.installLocation);
  48.         ...
  49.     }
  50. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  51.     private void handleReturnCode(InstallRequest installRequest) {
  52.         processPendingInstall(installRequest);
  53.     }
  54. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  55.     private void processPendingInstall(InstallRequest installRequest) {
  56.         if (mRet == PackageManager.INSTALL_SUCCEEDED) {
  57.             //拷贝apk
  58.             mRet = copyApk(installRequest);
  59.         }
  60.         ...
  61.         if (mParentInstallingSession != null) {
  62.             ...
  63.         } else {
  64.             //异步进行安装工作
  65.             mPm.mHandler.post(() -> processInstallRequests(
  66.                     mRet == PackageManager.INSTALL_SUCCEEDED /* success */,
  67.                     Collections.singletonList(installRequest)));
  68.         }
  69.     }
  70. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  71.     private int copyApk(InstallRequest request) {
  72.         if (mMoveInfo == null) {
  73.             return copyApkForFileInstall(request);
  74.         } else {
  75.             ...
  76.         }
  77.     }
  78. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  79.     private int copyApkForFileInstall(InstallRequest request) {
  80.         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
  81.         try {
  82.             ...
  83.             //拷贝codeFile
  84.             ret = PackageManagerServiceUtils.copyPackage(
  85.                     mOriginInfo.mFile.getAbsolutePath(), request.getCodeFile());
  86.             ...
  87.             try {
  88.                 //拷贝native lib库
  89.                 ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
  90.                         request.getAbiOverride(), isIncremental);
  91.                 ...
  92.             }
  93.             ...
  94.         }
  95.         ...
  96.     }
复制代码
3.8 AppDataHelper.prepareAppDataPostCommitLIF

    安装第三步:安装应用

  • 解析apk,把结果生存在ParsedPakcage中
  • 将包重定名为终极存放位置
  • 冻结进程
  • 判定包是否有用
  • 检索包名判定是否合法
  • 调用Installd进程进行安装工作
  1. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  2.     private void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
  3.         ...
  4.         processApkInstallRequests(success, installRequests);
  5.     }
  6. //frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
  7.     private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
  8.         if (!success) {
  9.             ...
  10.         } else {
  11.             mInstallPackageHelper.installPackagesTraced(installRequests);
  12.             for (InstallRequest request : installRequests) {
  13.                 request.onInstallCompleted();
  14.                 doPostInstall(request);
  15.             }
  16.         }
  17.         for (InstallRequest request : installRequests) {
  18.             mInstallPackageHelper.restoreAndPostInstall(request);
  19.         }
  20.     }
  21. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  22.     void installPackagesTraced(List<InstallRequest> requests) {
  23.         synchronized (mPm.mInstallLock) {
  24.             try {
  25.                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
  26.                 installPackagesLI(requests);
  27.             } finally {
  28.                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  29.             }
  30.         }
  31.     }
  32. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  33.     private void installPackagesLI(List<InstallRequest> requests) {
  34.         ...
  35.         try {
  36.             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
  37.             for (InstallRequest request : requests) {
  38.                 try {
  39.                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
  40.                     ...
  41.                     preparePackageLI(request);
  42.                 } catch (PrepareFailure prepareFailure) {
  43.                     ...
  44.                 } finally {
  45.                     ...
  46.                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  47.                 }
  48.                 ...
  49.                 try {
  50.                     request.onScanStarted();
  51.                     final ScanResult scanResult = scanPackageTracedLI(...);
  52.                 }
  53.             }
  54.             ...
  55.             synchronized (mPm.mLock) {
  56.                 try {
  57.                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
  58.                     //对多个apk进行一致性处理
  59.                     reconciledPackages = ReconcilePackageUtils.reconcilePackages(...);
  60.                 } catch (ReconcileFailure e) {
  61.                     ...
  62.                 } finally {
  63.                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  64.                 }
  65.                 try {
  66.                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
  67.                     commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
  68.                     success = true;
  69.                 } finally {
  70.                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  71.                 }
  72.             }
  73.             executePostCommitStepsLIF(reconciledPackages);
  74.         }
  75.     }
  76. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  77.     private void preparePackageLI(InstallRequest request) throws PrepareFailure {
  78.         ...
  79.         //解析apk,主要是解析apk的AndroidManifest.xml,并把结果保存在ParsedPackage中
  80.         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
  81.         final ParsedPackage parsedPackage;
  82.         try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
  83.             parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
  84.             AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
  85.         } catch (PackageManagerException e) {
  86.             ...
  87.         } finally {
  88.             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  89.         }
  90.         ...
  91.         //如果有静态共享库,则重命名静态共享库的名字,拼接上应用包名
  92.         if (parsedPackage.isStaticSharedLibrary()) {
  93.             // Static shared libraries have synthetic package names
  94.             PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
  95.         }
  96.         ...
  97.         synchronized (mPm.mLock) {
  98.             //如果是安装已有应用,进行sdk和persistent判断
  99.             if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
  100.                 ...
  101.             }
  102.             //从现有PackageSetting列表中尝试通过包名获取PackageSetting,安装新应用时,ps为空
  103.             PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
  104.             PackageSetting signatureCheckPs = ps;
  105.             ...
  106.             //检查申明权限的合法性,权限是否已经被其他应用申明
  107.             final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
  108.             for (int groupNum = 0; groupNum < numGroups; groupNum++) {
  109.                 ...
  110.             }
  111.             ...
  112.             //在PermissionManagerService进行权限兼容性的检查
  113.             final int n = ArrayUtils.size(parsedPackage.getPermissions());
  114.             for (int i = n - 1; i >= 0; i--) {
  115.                 ...
  116.             }
  117.             ...
  118.         }
  119.         ...
  120.         if (!isApex) {
  121.             //将包重命名为最终存放位置
  122.             doRenameLI(request, parsedPackage);
  123.             ...
  124.         } else {
  125.             ...
  126.         }
  127.         //应用安装期间,冻结进程
  128.         final PackageFreezer freezer =
  129.                 freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags,
  130.                         "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED);
  131.         ...
  132.         try {
  133.             ...
  134.             //更新信息到InstallRequest
  135.             request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
  136.                     oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
  137.                     ps, disabledPs);
  138.         }
  139.         ...
  140.     }
  141. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  142.     private ScanResult scanPackageTracedLI(...) throws PackageManagerException {
  143.         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
  144.         try {
  145.             return scanPackageNewLI(...);
  146.         } finally {
  147.             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  148.         }
  149.     }
  150. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  151.     private ScanResult scanPackageNewLI(...)
  152.             throws PackageManagerException {
  153.         ...
  154.         synchronized (mPm.mLock) {
  155.             //判断包是否是有效的
  156.             assertPackageIsValid(parsedPackage, parseFlags, newScanFlags);
  157.             final ScanRequest request = new ScanRequest(...);
  158.             //检索包名,判断合法性
  159.             return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest,
  160.                     currentTime);
  161.         }
  162.     }
  163. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  164.     private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages,
  165.             @NonNull int[] allUsers) {
  166.         for (ReconciledPackage reconciledPkg : reconciledPackages) {
  167.             ...
  168.             //非第一次安装
  169.             if (installRequest.isInstallReplace()) {...}
  170.             ...
  171.             //更新应用信息到PackageSetting中
  172.             AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers);
  173.             //更新应用信息到PMS.Settings中
  174.             updateSettingsLI(pkg, allUsers, installRequest);
  175.             ...
  176.         }
  177.     }
  178. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  179.     private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
  180.         for (ReconciledPackage reconciledPkg : reconciledPackages) {
  181.             ...
  182.             //安装应用
  183.             mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
  184.             ...
  185.     }
  186. //frameworks/base/services/core/java/com/android/server/pm/AppDataHelper.java
  187.     public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
  188.         ...
  189.         for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
  190.             final int flags;
  191.             //判断安装路径
  192.             if (StorageManager.isUserKeyUnlocked(user.id)
  193.                     && smInternal.isCeStoragePrepared(user.id)) {
  194.                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
  195.             } else if (umInternal.isUserRunning(user.id)) {
  196.                 flags = StorageManager.FLAG_STORAGE_DE;
  197.             } else {
  198.                 continue;
  199.             }
  200.             if (ps.getInstalled(user.id)) {
  201.                 //准备应用数据
  202.                 prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
  203.                     ...
  204.                 });
  205.             }
  206.         }
  207.         //以阻塞方式执行此批收集的所有待处理操作
  208.         executeBatchLI(batch);
  209.     }
复制代码
3.9 ArtManagerLocal.dexoptPackage

    安装第四步:dex优化
调用AndroidRuntime进程dex优化工作
  1. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  2.     private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
  3.         for (ReconciledPackage reconciledPkg : reconciledPackages) {
  4.             ...
  5.             //安装应用
  6.             mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
  7.             ...
  8.             //判断是否需要做dex优化
  9.             final boolean performDexopt =
  10.                     (!instantApp || android.provider.Settings.Global.getInt(
  11.                             mContext.getContentResolver(),
  12.                             android.provider.Settings.Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
  13.                             && !pkg.isDebuggable()
  14.                             && (!onIncremental)
  15.                             && dexoptOptions.isCompilationEnabled()
  16.                             && !isApex;
  17.             //需要做dex优化
  18.             if (performDexopt) {
  19.                 ...
  20.                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
  21.                 ...
  22.                 //使用AndroidRuntime服务
  23.                 if (useArtService()) {
  24.                     PackageManagerLocal packageManagerLocal =
  25.                             LocalManagerRegistry.getManager(PackageManagerLocal.class);
  26.                     try (PackageManagerLocal.FilteredSnapshot snapshot =
  27.                                     packageManagerLocal.withFilteredSnapshot()) {
  28.                         DexoptParams params =
  29.                                 dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
  30.                         //在ART里做dex优化
  31.                         DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
  32.                                 snapshot, packageName, params);
  33.                         installRequest.onDexoptFinished(dexOptResult);
  34.                     }
  35.                 } else {
  36.                     ...
  37.                 }
  38.                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  39.             }
  40.             ...
  41.     }
复制代码
3.10 PackageManagerService.finishPackageInstall

应用安装完成后,会发送ACTION_PACKAGE_ADDED/ACTION_PACKAGE_REPLACED/ACTION_PACKAGE_CHANGED广播,并触发PackageInstallObserver的onPackageInstalled函数回调
  1. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  2.     public void restoreAndPostInstall(InstallRequest request) {
  3.         ...
  4.         if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED && doRestore) {
  5.             //解冻进程
  6.             request.closeFreezer();
  7.             //对给定的Request进行BackupManager还原
  8.             doRestore = performBackupManagerRestore(userId, token, request);
  9.         }
  10.         ...
  11.     }
  12. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  13.     private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) {
  14.         ...
  15.         IBackupManager iBackupManager = mInjector.getIBackupManager();
  16.         if (iBackupManager != null) {
  17.             ...
  18.             Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
  19.             try {
  20.                 if (iBackupManager.isUserReadyForBackup(userId)) {
  21.                     iBackupManager.restoreAtInstallForUser(
  22.                             userId, request.getPkg().getPackageName(), token);
  23.                 } else {
  24.                     ...
  25.                 }
  26.             }
  27.             ...
  28.         }
  29.         ...
  30.     }
  31. //frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
  32.     public void restoreAtInstallForUser(int userId, String packageName, int token)
  33.             throws RemoteException {
  34.         if (isUserReadyForBackup(userId)) {
  35.             restoreAtInstall(userId, packageName, token);
  36.         }
  37.     }
  38. //frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
  39.     public void restoreAtInstall(@UserIdInt int userId, String packageName, int token) {
  40.         UserBackupManagerService userBackupManagerService =
  41.                 getServiceForUserIfCallerHasPermission(userId, "restoreAtInstall()");
  42.         if (userBackupManagerService != null) {
  43.             userBackupManagerService.restoreAtInstall(packageName, token);
  44.         }
  45.     }
  46. //frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
  47.     public void restoreAtInstall(String packageName, int token) {
  48.         ...
  49.         boolean skip = false;
  50.         //这里获取到的restoreSet值是0
  51.         long restoreSet = getAvailableRestoreToken(packageName);
  52.         ...
  53.         if (restoreSet == 0) {
  54.             skip = true;
  55.         }
  56.         ...
  57.         if (skip) {
  58.             ...
  59.             try {
  60.                 mPackageManagerBinder.finishPackageInstall(token, false);
  61.             } catch (RemoteException e) { /* can't happen */ }
  62.         }
  63.     }
  64. //frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
  65.     void finishPackageInstall(int token, boolean didLaunch) {
  66.         ...
  67.         final Message msg = mHandler.obtainMessage(PackageManagerService.POST_INSTALL, token,
  68.                 didLaunch ? 1 : 0);
  69.         mHandler.sendMessage(msg);
  70.     }
  71. //frameworks/base/services/core/java/com/android/server/pm/PackageHandler.java
  72.     void doHandleMessage(Message msg) {
  73.         switch (msg.what) {
  74.             case POST_INSTALL: {
  75.                 ...
  76.                 request.closeFreezer();
  77.                 request.runPostInstallRunnable();
  78.                 if (!request.isInstallExistingForUser()) {
  79.                     mInstallPackageHelper.handlePackagePostInstall(request, didRestore);
  80.                 }
  81.                 ...
  82.             } break;
  83.         }
  84.     }
  85. //frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
  86.     void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) {
  87.         ...
  88.         final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
  89.         ...
  90.         if (succeeded) {
  91.             //没有静态库
  92.             if (request.getPkg().getStaticSharedLibraryName() == null) {
  93.                 ...
  94.             } else if (!ArrayUtils.isEmpty(request.getLibraryConsumers())) {//有静态库
  95.                 ...
  96.                 for (int i = 0; i < request.getLibraryConsumers().size(); i++) {
  97.                     //发送package changed广播
  98.                     mPm.sendPackageChangedBroadcast(...);
  99.                 }
  100.             }
  101.         ...
  102.         ...
  103.         final boolean deferInstallObserver = succeeded && update;
  104.         if (deferInstallObserver) {
  105.             ...
  106.         } else {
  107.             //触发安装完成的回调
  108.             mPm.notifyInstallObserver(request);
  109.         }
  110.         ...
  111.     }
  112. //frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
  113.     void sendPackageChangedBroadcast(...) {
  114.         ...
  115.         mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast(
  116.                 packageName, dontKillApp, componentNames, packageUid, reason, userIds,
  117.                 instantUserIds, broadcastAllowList));
  118.     }
  119. //frameworks/base/services/core/java/com/android/server/pm/BroadcastHelper.java
  120.     public void sendPackageChangedBroadcast(...) {
  121.         ...
  122.         sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
  123.                 userIds, instantUserIds, broadcastAllowList, null /* filterExtrasForReceiver */,
  124.                 null /* bOptions */);
  125.     }
  126. //frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
  127.     void notifyInstallObserver(InstallRequest request) {
  128.         if (request.getObserver() != null) {
  129.             try {
  130.                 Bundle extras = extrasForInstallResult(request);
  131.                 //触发安装完成的回调
  132.                 request.getObserver().onPackageInstalled(request.getName(),
  133.                         request.getReturnCode(), request.getReturnMsg(), extras);
  134.             } catch (RemoteException e) {
  135.                 Slog.i(TAG, "Observer no longer exists.");
  136.             }
  137.         }
  138.     }
复制代码

四:小结

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等体系广播来实现此功能,不外广播及时性较差。
  1.         final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
  2.             @Override
  3.             public void onUserActionRequired(Intent intent) {
  4.                 throw new IllegalStateException();
  5.             }
  6.             @Override
  7.             public void onPackageInstalled(String basePackageName, int returnCode, String msg,
  8.                     Bundle extras) {
  9.                 if (returnCode == INSTALL_SUCCEEDED) {
  10.                     future.complete(new InstallResult(PackageInstallerSession.this, extras));
  11.                 } else {
  12.                     future.completeExceptionally(new PackageManagerException(returnCode, msg));
  13.                 }
  14.             }
  15.         };
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表