一:背景
应用下载安装是用户很常用的场景之一,如果有两个同范例的应用A和B,功能、UI相差不多,但是A应用安装必要3s,B应用安装只必要1s,那么无疑B应用会更受用户欢迎。怎样减少应用安装时间,那就必须要了解应用安装过程中必要做哪些事变,耗时点在哪里。
那么应用安装过程中体系到底做了哪些事变呢,且看下文。
二:安装方式
应用安装有4种方式
1. 体系预置应用:包罗体系应用和预置应用。在开机过程中完成安装,静默安装,没有安装界面,用户无法感知。
2. 使用adb安装:adb install A.apk,静默安装,没有安装界面,如果安装失败会有具体的报错信息显示。
3. 应用商店下载安装:静默安装,没有安装界面,下载完成后会自动安装。
4. 用户点击存储里的apk安装包进行安装:有安装界面及安装进度显示,必要触发安装apk动作的应用有安装权限。
下面将从第四种安装方式来剖析安装流程
三:PackageInstaller安装应用
当用户点击存储里的apk安装包时,体系辨认到这是一个apk,会启动PackageInstaller进程的InstallStart Activity来触发apk的安装流程
3.1 InstallStart.onCreate
InstallStart启动后,会根据传进来的intent判定是否是install范例的session,如果是则启动PackageInstallerActivity来显示安装界面。
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- ...
- //这里传入的action是android.content.pm.action.CONFIRM_INSTALL,所以isSessionInstall为true
- final boolean isSessionInstall =
- PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
- || PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
- ...
- Intent nextActivity = new Intent(intent);
- ...
- //isSessionInstall为true,启动PackageInstallerActivity
- if (isSessionInstall) {
- nextActivity.setClass(this, PackageInstallerActivity.class);
- }
- ...
- if (nextActivity != null) {
- try {
- startActivity(nextActivity);
- } catch (SecurityException e) {
- ...
- }
- }
- finish();
- }
复制代码 3.2 PackageInstallerActivity.bindUi
PackageInstallerActivity启动后,会先解析被安装应用的AndroidManifest,获取应用的安装名和icon等信息,生存在AppSinppet对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了

- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- protected void onCreate(Bundle icicle) {
- ...
- if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(action)) {
- final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
- -1 /* defaultValue */);
- final SessionInfo info = mInstaller.getSessionInfo(sessionId);
- String resolvedPath = info != null ? info.getResolvedBaseApkPath() : null;
- ...
- //初始化mSessionId和packageSource
- mSessionId = sessionId;
- packageSource = Uri.fromFile(new File(resolvedPath));
- ...
- }
- ...
- final boolean wasSetUp = processAppSnippet(packageSource);
- ...
- }
- private boolean processAppSnippet(@NonNull Object source) {
- if (source instanceof Uri) {
- return processPackageUri((Uri) source);
- }
- ...
- }
- private boolean processPackageUri(final Uri packageUri) {
- ...
- switch (scheme) {
- case ContentResolver.SCHEME_FILE: {
- File sourceFile = new File(packageUri.getPath());
- //PackageUtil解析应用的AndroidManifest,获取应用的包名、版本号等信息
- mPkgInfo = PackageUtil.getPackageInfo(this, sourceFile,
- PackageManager.GET_PERMISSIONS);
- ...
- //获取应用的安装名和icon,保存在AppSnippet对象中
- mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
- } break;
- }
- }
- protected void onResume() {
- ...
- if (mAppSnippet != null) {
- //初始化弹框UI
- bindUi();
- //检查是否有安装权限,如果有则初始化安装UI
- checkIfAllowedAndInitiateInstall();
- }
- ...
- }
复制代码 3.3 PackageInstallerActivity.checkIfAllowedAndInitiateInstall
如果安装应用的应用没有安装未知泉源的权限,会启动提供用户开启允许安装来自未知应用的Dialog,用户点击Settings按钮,会注册UnknownSourcesListener的监听回调并启动体系-设置模块内里的Install unknown apps界面
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- private void checkIfAllowedAndInitiateInstall() {
- ...
- //检查应用是否有安装未知应用权限
- handleUnknownSources();
- }
- private void handleUnknownSources() {
- ...
- //获取应用的AppOps权限,默认是MODE_DEFAULT
- final int appOpMode = mAppOpsManager.noteOpNoThrow(...);
- switch (appOpMode) {
- case AppOpsManager.MODE_DEFAULT:
- mAppOpsManager.setMode(appOpStr, mOriginatingUid,
- mOriginatingPackage, AppOpsManager.MODE_ERRORED);
- case AppOpsManager.MODE_ERRORED:
- showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);
- break;
- ...
- }
- }
- private void showDialogInner(int id) {
- ...
- //根据传进来的id,判断要创建哪种dialog
- DialogFragment newDialog = createDialog(id);
- ...
- }
- private void showDialogInner(int id) {
- ...
- //根据传进来的id,判断要创建哪种dialog
- DialogFragment newDialog = createDialog(id);
- ...
- }
- private DialogFragment createDialog(int id) {
- switch (id) {
- ...
- case DLG_EXTERNAL_SOURCE_BLOCKED:
- return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
- ...
- }
- ...
- }
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.ExternalSourcesBlockedDialog.java
- public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
- ...
- protected Dialog createDialog(@NonNull CharSequence argument) {
- ...
- try {
- ...
- return new AlertDialog.Builder(activity)
- ...
- .setPositiveButton(R.string.external_sources_settings,
- (dialog, which) -> {
- ...
- try {
- //注册UnknownSourcesListener的监听回调
- activity.register(activity.new UnknownSourcesListener());
- //启动Settings里面的Install unknown apps界面,由用户选择是否要打开Allow from this source开关。开关打开后,会调用UnknownSourcesListener的onOpChanged回调函数
- activity.startActivityForResult(settingsIntent,
- REQUEST_TRUST_EXTERNAL_SOURCE);
- }
- ...
- })
- .setNegativeButton(R.string.cancel,
- (dialog, which) -> activity.finish())
- .create();
- }
- ...
- }
- }
复制代码 3.4 PackageInstallerActivity.initiateInstall
当用户在设置模块的允许安装未知泉源界面点击允许时,PackageInstallerActivity会收到onOpChanged的回调,再次启动PackageInstallerActivity,初始化安装UI
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.UnknownSourcesListener.java
- private class UnknownSourcesListener implements AppOpsManager.OnOpChangedListener {
- @Override
- public void onOpChanged(String op, String packageName) {
- ...
- //解绑监听
- unregister(this);
- ...
- new Handler(Looper.getMainLooper()).postDelayed(() -> {
- if (!isDestroyed()) {
- //启动PackageInstallerActivity
- startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
- }
- }, 500);
- }
- }
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- private void checkIfAllowedAndInitiateInstall() {
- if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
- //初始化安装UI
- initiateInstall();
- }
- ...
- }
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- private void initiateInstall() {
- ...
- startInstallConfirm();
- }
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- private void startInstallConfirm() {
- TextView viewToEnable;
- if (mAppInfo != null) {
- ...
- } else {
- // This is a new application with no permissions.
- viewToEnable = requireViewById(R.id.install_confirm_question);
- }
- viewToEnable.setVisibility(View.VISIBLE);
- mEnableOk = true;
- //设置mOk为可点击的状态
- mOk.setEnabled(true);
- mOk.setFilterTouchesWhenObscured(true);
- }
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- private void bindUi() {
- ...
- mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
- (ignored, ignored2) -> {
- if (mOk.isEnabled()) {
- if (mSessionId != -1) {
- setActivityResult(RESULT_OK);
- finish();
- }
- ...
- }
- }, null);
- ...
- }
复制代码 3.5 PackageInstallerSession.handleInstall
当用户点击Install按钮后,安装界面的Dialog会消失,终极会调用到PackageInstallerSession的handleInstall函数来触发安装流程。
- //frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
- public void finish() {
- if (mSessionId != -1) {
- if (mActivityResultCode == Activity.RESULT_OK) {
- mInstaller.setPermissionsResult(mSessionId, true);
- }
- ...
- }
- ...
- }
- //frameworks/base/core/java/android/content/pm/PackageInstaller.java
- public void setPermissionsResult(int sessionId, boolean accepted) {
- try {
- mInstaller.setPermissionsResult(sessionId, accepted);
- }
- ...
- }
- //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
- public void setPermissionsResult(int sessionId, boolean accepted) {
- //检查应用是否有INSTALL_PACKAGES权限
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
- synchronized (mSessions) {
- PackageInstallerSession session = mSessions.get(sessionId);
- if (session != null) {
- session.setPermissionsResult(accepted);
- }
- }
- }
- //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
- void setPermissionsResult(boolean accepted) {
- ...
- if (accepted) {
- ...
- //isCommitted()为true,这里会发送MSG_INSTALL类型的message
- root.mHandler.obtainMessage(
- isCommitted() ? MSG_INSTALL : MSG_PRE_APPROVAL_REQUEST).sendToTarget();
- }
- ...
- }
- //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
- private final Handler.Callback mHandlerCallback = new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- ...
- case MSG_INSTALL:
- //触发安装流程
- handleInstall();
- break;
- ...
- }
- ...
- }
- };
- //frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
- private void handleInstall() {
- ...
- //校验
- verify();
- }
复制代码 3.6 PackageInstallerSession.verify
安装第一步:校验。
- 解析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
安装第二步:拷贝
- //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企服之家,中国第一个企服评测及商务社交产业平台。 |