Android应用安装流程(AndroidU)

Android应用安装流程(AndroidU)应用安装 androidu

大家好,欢迎来到IT知识分享网。

一:背景

    应用下载安装是用户很常用的场景之一,如果有两个同类型的应用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对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了

Android应用安装流程(AndroidU)

//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界面

Android应用安装流程(AndroidU)

Android应用安装流程(AndroidU)

//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

Android应用安装流程(AndroidU)

//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函数来触发安装流程。

Android应用安装流程(AndroidU)

//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)); } } };

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/128134.html

(0)
上一篇 2025-09-02 20:20
下一篇 2025-09-02 20:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信