Loading...
墨滴

帅次

2021/10/27  阅读:20  主题:自定义主题1

❤️Android 源码解读-应用的安装过程 ❤️

关注:微信公众号「帅次」,获取更多内容。

App安装过程

源码:Android SDK 30

当我们点击某一个 App 安装包进行安装时,首先会弹出一个系统界面指示我们进行安装操作。这个界面是 Android Framework 中预置的一个 Activity—PackageInstallerActivity.java

PackageInstallerActivity

frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

/**
 */

public class PackageInstallerActivity extends AlertActivity {
      ...
}

看到 Activity 当然是先从 onCreate() 开始了

onCreat()

public class PackageInstallerActivity extends AlertActivity {
    @Override
    protected void onCreate(Bundle icicle) {
        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);

        super.onCreate(null);

        if (icicle != null) {
            mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
        }

        //mPm = PackageManagerService
        mPm = getPackageManager();
        //mIpm = IPackageManager
        //将原始接口返回给包管理器。
        mIpm = AppGlobals.getPackageManager();
        //AppOpsManager 涵盖了从帮助运行时权限访问控制和跟踪到电池消耗跟踪的各种功能。
        mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
        //提供在设备上安装、升级和删除应用程序的能力。
        mInstaller = mPm.getPackageInstaller();
        //在多用户系统上管理用户和用户详细信息
        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);

        final Intent intent = getIntent();
        ...
        //安装包Uri
        final Uri packageUri;

        if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
            //获取android.content.pm.extra.SESSION_ID
            final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
            //获取安装Session的详细信息
            final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
            if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
                //获取SessionInfo失败退出安装
                finish();
                return;
            }

            mSessionId = sessionId;
            packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
            mOriginatingURI = null;
            mReferrerURI = null;
        } else {
            mSessionId = -1;
            packageUri = intent.getData();
            mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
            mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
        }

        if (packageUri == null) {
            //获取packageUri失败退出安装
            setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
            finish();
            return;
        }
        //解析 Uri 并为此包设置安装程序。
        boolean wasSetUp = processPackageUri(packageUri);
        if (!wasSetUp) {
            return;
        }
    }
}

在 onCreate() 方法中,首先执行一些初始化操作,获取PackageManager和PackageInstaller、UserManager等对象,根据当前Intent的信息最一些逻辑判断并弹出消息弹窗,然后获取一些安装包信息。接下来咱们安装 Activity 的生命周期往下看 onStart() 没有重写,咱继续往下看

onResume()

    @Override
    protected void onResume() {
        super.onResume();
        //processPackageUri已拿到mAppSnippet
        if (mAppSnippet != null) {
            // 在禁用确定按钮的情况下加载虚拟布局,直到我们覆盖此布局
            // 开始安装确认
            bindUi();
            // 检查是否允许安装包,如果允许则启动安装。 
            //如果不允许显示适当的对话框。
            checkIfAllowedAndInitiateInstall();
        }

        if (mOk != null) {
            mOk.setEnabled(mEnableOk);
        }
    }

bindUi()

    private void bindUi() {
        ...
        mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
                (ignored, ignored2) -> {
                    if (mOk.isEnabled()) {
                        ...
                            startInstall();
                        ...
                    }
                }, null);
        ...
    }

这里点击安装按钮进去 startInstall() 方法,失败的情况咱就不看了,继续往下走着。

startInstall()

    private void startInstall() {
        // 启动子Activity,安装应用程序
        Intent newIntent = new Intent();
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
                mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        newIntent.setClass(this, InstallInstalling.class);
        ...
        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        startActivity(newIntent);
        finish();
    }

startInstall 调用即使启用了一个新的Activity–>InstallInstalling。会把安装包的信息通过 Intent 传递到 InstallInstalling 这个 Activity。

InstallInstalling

frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

/**
 * Send package to the package manager and handle results from package manager. Once the
 * installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}.
 * <p>This has two phases: First send the data to the package manager, then wait until the package
 * manager processed the result.</p>
 */

public class InstallInstalling extends AlertActivity {
      ...
}

在这个页面点击安装时,InstallInstalling 的作用主要是向 PMS 发送包信息以及处理回调。 这有两个阶段:

  • 首先将数据发送给 PackageManager ;
  • 等待 PackageManager 处理结果(InstallSuccess 或 InstallFailed)。

看到 Activity 当然是先从 onCreate() 开始了

onCreat()

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ApplicationInfo appInfo = getIntent()
                .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
        //要安装的包的 URI
        mPackageURI = getIntent().getData();
        if ("package".equals(mPackageURI.getScheme())) {
            try {
                //注释1:安装现有包
                getPackageManager().installExistingPackage(appInfo.packageName);
                //安装成功页面
                launchSuccess();
            } catch (PackageManager.NameNotFoundException e) {
                //安装失败页面
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        } else {
             //注释2:没有现有包
             //根据 mPackageURI 创建一个对应的 File
            final File sourceFile = new File(mPackageURI.getPath());
            //显示应用信息 icon,应用名
            PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);

            mAlert.setIcon(as.icon);
            ...
            if (savedInstanceState != null) {
                //咱们第一次仅savedInstanceState==null
                //安装包的会话 ID
                mSessionId = savedInstanceState.getInt(SESSION_ID);
                //我们等待的安装事件的 ID
                mInstallId = savedInstanceState.getInt(INSTALL_ID);
                //重新登记结果;如果结果是在 Activtiy 被销毁时交付的,则可能会立即回调
                try {
                    //添加一个观察者。如果此id已存在事件,请在此调用内回调。
                    // 向 InstallEventReceiver 注册一个观察者
                    // InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件
                    // 这里事件会回调给 this::launchFinishBasedOnResult
                    InstallEventReceiver.addObserver(this, mInstallId,
                            this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    // Does not happen
                }
            } else {
                //咱们第一次仅savedInstanceState==null
                
                //创建 SessionParams,它用来携带会话的参数
                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                params.setInstallAsInstantApp(false);
                ...
                params.setInstallReason(PackageManager.INSTALL_REASON_USER);

                File file = new File(mPackageURI.getPath());
                try {
                    // 对 APK 进行轻量级的解析,并将解析的结果赋值给 SessionParams 相关字段 
                    PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
                    params.setAppPackageName(pkg.packageName);
                    params.setInstallLocation(pkg.installLocation);
                    params.setSize(
                            PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
                } catch (PackageParser.PackageParserException e) {
                    ...
                } catch (IOException e) {
                    ...
                }

                try {
                    // 向 InstallEventReceiver 注册一个观察者返回一个新的 mInstallId
                    // InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件
                    // 这里事件会回调给 this::launchFinishBasedOnResult
                    mInstallId = InstallEventReceiver
                            .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                    this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }

                try {
                    //PackageInstaller 的 createSession 
                    //方法内部会通过 IPackageInstaller 与 PackageInstallerService进行进程间通信,
                    //最终调用的是 PackageInstallerService 的 createSession 方法来创建并返回 mSessionId
                    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
                } catch (IOException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }
            }

            mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);

            //监听会话的更改并更新进度条
            mSessionCallback = new InstallSessionCallback();
        }
    }

NameNotFoundException:当找不到给定的包、应用程序或组件名称时,将引发此异常。

在 onCreate() 方法中,首先执行一些初始化操作,比如获取 mInstallId、mSessionId以及监听回调 mSessionCallback 。接下来看看 onStart() 。

onStart()

    @Override
    protected void onStart() {
        super.onStart();

        //设置回话监听回调
        getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback);
    }

onResume()

    @Override
    protected void onResume() {
        super.onResume();

        //This is the first onResume in a single life of the activity
        if (mInstallingTask == null) {
            //PackageInstaller:提供在设备上安装、升级和删除应用程序的能力。
            //这包括支持打包为单个“整体”APK 的应用程序或打包为多个“拆分”APK 的应用程序。
            PackageInstaller installer = getPackageManager().getPackageInstaller();
            //安装Session的详细信息
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

            if (sessionInfo != null && !sessionInfo.isActive()) {
                //创建mInstallingTask并启动
                mInstallingTask = new InstallingAsyncTask();
                mInstallingTask.execute();
            } else {
                // 安装完成后我们会收到广播
                //mCancelButton不允许点击
                mCancelButton.setEnabled(false);
                //Activity.setFinishOnTouchOutside():设置此活动在其窗口边界外触摸
                setFinishOnTouchOutside(false);
            }
        }
    }

InstallingAsyncTask

    /**
     * Send the package to the package installer and then register a event result observer that
     * will call {@link #launchFinishBasedOnResult(int, int, String)}
     */

    private final class InstallingAsyncTask extends AsyncTask<VoidVoid,
            PackageInstaller.Session
{
        volatile boolean isDone;

        @Override
        protected PackageInstaller.Session doInBackground(Void... params) {
            PackageInstaller.Session session;
            try {
                //打开现有Session
                session = getPackageManager().getPackageInstaller().openSession(mSessionId);
            } catch (IOException e) {
                synchronized (this) {
                    isDone = true;
                    notifyAll();
                }
                return null;
            }
            //设置暂存此会话的当前进度(0-1z之间)。
            session.setStagingProgress(0);

            try {
                File file = new File(mPackageURI.getPath());

                //输入流in
                try (InputStream in = new FileInputStream(file)) {
                    long sizeBytes = file.length();
                    //打开一个流以将 APK 文件写入会话。
                    try (OutputStream out = session
                            .openWrite("PackageInstaller"0, sizeBytes)) {
                        byte[] buffer = new byte[1024 * 1024];
                        //写入文件
                        while (true) {
                            int numRead = in.read(buffer);

                            if (numRead == -1) {
                                session.fsync(out);
                                break;
                            }

                            if (isCancelled()) {
                                session.close();
                                break;
                            }

                            //将 APK 文件通过 IO 流的形式写入到 PackageInstaller.Session 中
                            out.write(buffer, 0, numRead);
                            if (sizeBytes > 0) {
                                float fraction = ((float) numRead / (float) sizeBytes);
                                session.addProgress(fraction);
                            }
                        }
                    }
                }

                return session;
            } catch (IOException | SecurityException e) {
                Log.e(LOG_TAG, "Could not write package", e);

                session.close();

                return null;
            } finally {
                synchronized (this) {
                    isDone = true;
                    notifyAll();
                }
            }
        }

        @Override
        protected void onPostExecute(PackageInstaller.Session session) {
            if (session != null) {
                //包已下载好,设置安装提交广播
                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntent.setPackage(getPackageName());
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallInstalling.this,
                        mInstallId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);

                // 调用 PackageInstaller.Session 的 commit 方法,进行安装
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }
    }

其他没啥好看的,咱么看看具体的session.commit

PackageInstaller.commit()

        public void commit(@NonNull IntentSender statusReceiver) {
            try {
                mSession.commit(statusReceiver, false);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

mSession 就是 IPackageInstallerSession 。这说明要通过 IPackageInstallerSession 来进行进程间的通信,最终会调用PackageInstallerSession 的 commit 方法

PackageInstallerSession

frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

public class PackageInstallerSession extends IPackageInstallerSession.Stub {
      ...
}

commit()

    @Override
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
        if (hasParentSessionId()) {
            throw new IllegalStateException(
                    "Session " + sessionId + " is a child of multi-package session "
                            + mParentSessionId +  " and may not be committed directly.");
        }

        if (!markAsSealed(statusReceiver, forTransfer)) {
            return;
        }
        //return true 多个包
        if (isMultiPackage()) {
            ...
        }

        dispatchStreamValidateAndCommit();
    }

dispatchStreamValidateAndCommit()

    private void dispatchStreamValidateAndCommit() {
        // 通过 Handler 处理消息事件
        mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
    }

mHandler()

    Handler mHandler = new Handler(looper, mHandlerCallback);
    private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_STREAM_VALIDATE_AND_COMMIT:
                    handleStreamValidateAndCommit();
                    break;
                ...
            }

            return true;
        }
    };

handleStreamValidateAndCommit

    private void handleStreamValidateAndCommit() {
        PackageManagerException unrecoverableFailure = null;
        // 这将跟踪会话和任何子项是否已通过验证并准备好进入下一安装阶段
        boolean allSessionsReady = false;
        try {
            allSessionsReady = streamValidateAndCommit();
        } catch (PackageManagerException e) {
            unrecoverableFailure = e;
        }

        //多包,不是多包直接过
        if (isMultiPackage()) {
            ....
        }

        if (!allSessionsReady) {
            return;
        }

        // 通过 Handler 处理MSG_INSTALL消息事件
        mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
    }

mHandler()

    Handler mHandler = new Handler(looper, mHandlerCallback);
    private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                ...
                case MSG_INSTALL:
                    handleInstall();
                    break;
                ...
            }

            return true;
        }
    };

查看 mHnadler() 发现 MSG_INSTALL 调用的是 handleInstall()。

handleInstall()

    private void handleInstall() {
        ...
        //return true 会话被再次启用。
        if (params.isStaged) {
            mStagingManager.commitSession(this);
            destroyInternal();
            dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged"null);
            return;
        }
        ...
        // 对于 multiPackage 会话,读取锁外的子会话,
        // 因为读取持有锁的子会话可能会导致死锁 (b/123391593)。
        List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();

        try {
            synchronized (mLock) {
                //接下来咱们就看看此方法
                installNonStagedLocked(childSessions);
            }
        } catch (PackageManagerException e) {
            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
            Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
            destroyInternal();
            dispatchSessionFinished(e.error, completeMsg, null);
        }
    }

installNonStagedLocked()

    @GuardedBy("mLock")
    private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
            throws PackageManagerException 
{
        final PackageManagerService.ActiveInstallSession installingSession =
                makeSessionActiveLocked();
        if (installingSession == null) {
            return;
        }
        //return true 多个包
        if (isMultiPackage()) {
            List<PackageManagerService.ActiveInstallSession> installingChildSessions =
                    new ArrayList<>(childSessions.size());
            ...
            mPm.installStage(installingChildSessions);
        } else {
            mPm.installStage(installingSession);
        }
    }

这里不管不管怎么样都会调用 mPm.installStage(installingChildSessions);

mPm 就是系统服务 PackageManagerService。

PackageManagerService

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender 
{
}

installStage()

installStage 方法就是正式开始 apk 的安装过程。这个过程包括两大步:

  • 安装包;
  • 装载代码
    void installStage(ActiveInstallSession activeInstallSession) {
        ...
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        //把之前传入的 sessionParams 安装信息,及其它信息封装成 InstallParams
        final InstallParams params = new InstallParams(activeInstallSession);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;

        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
                System.identityHashCode(msg.obj));
        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                System.identityHashCode(msg.obj));

        mHandler.sendMessage(msg);
    }

    void installStage(List<ActiveInstallSession> children)
            throws PackageManagerException 
{
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        final MultiPackageInstallParams params =
                new MultiPackageInstallParams(UserHandle.ALL, children);
        params.setTraceMethod("installStageMultiPackage")
                .setTraceCookie(System.identityHashCode(params));
        msg.obj = params;

        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
                System.identityHashCode(msg.obj));
        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                System.identityHashCode(msg.obj));
        mHandler.sendMessage(msg);
    }

MultiPackageInstallParams:多包安装的容器,指的是一起提交的所有安装会话和参数。

这两个方法很详细就是把之前传入的 sessionParams 安装信息及其它信息封装成 InstallParams(MultiPackageInstallParams)。

mHandler 发送的消息 INIT_COPY 从名字上就知道是去初始化复制。

mHandler()

    class PackageHandler extends Handler {
        PackageHandler(Looper looper) {
            super(looper);
        }
        public void handleMessage(Message msg) {
            try {
                doHandleMessage(msg);
            } finally {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            }
        }
        void doHandleMessage(Message msg) {
            switch (msg.what) {
                case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    if (params != null) {
                        if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                System.identityHashCode(params));
                        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                        params.startCopy();
                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                    }
                    break;
                }
                ...
            }
        }
    }

HandlerParams.startCopy()

    private abstract class HandlerParams {
        /** User handle for the user requesting the information or installation. */
        private final UserHandle mUser;
        String traceMethod;
        int traceCookie;
        ...
        final void startCopy() {
            if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
            handleStartCopy();
            handleReturnCode();
        }

        abstract void handleStartCopy();
        abstract void handleReturnCode();
    }

startCopy(),里面有两个抽象方法,咱只能去找他的实现类 InstallParams 里面的这两个方法了。

InstallParams

    class InstallParams extends HandlerParams {
        ...
            /*
         * 调用远程方法来获取包信息和安装位置值。
         * 如果需要,根据默认策略覆盖安装位置,然后根据安装位置创建安装参数。
         */

        public void handleStartCopy() {
            int ret = PackageManager.INSTALL_SUCCEEDED;

            // 表示文件已下载,不需要再次下载。
            if (origin.staged) {
                 // 设置安装标志位,决定是安装在手机内部存储空间还是 sdcard 中
                if (origin.file != null) {
                    installFlags |= PackageManager.INSTALL_INTERNAL;
                } else {
                    throw new IllegalStateException("Invalid stage location");
                }
            }

            // 判断安装位置
            final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
            final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
            PackageInfoLite pkgLite = null;


            //解析给定的包并返回最少的细节。
            pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                    origin.resolvedPath, installFlags, packageAbiOverride);

            if (DEBUG_INSTANT && ephemeral) {
                Slog.v(TAG, "pkgLite for install: " + pkgLite);
            }

            /*
             * 如果我们的可用空间太少,请在放弃之前尝试释放缓存。
             */

            if (!origin.staged && pkgLite.recommendedInstallLocation
                    == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                // TODO: 释放目标设备上的磁盘空间
                final StorageManager storage = StorageManager.from(mContext);
                //返回给定路径被(Environment.getDataDirectory())认为存储空间不足的可用字节数。
                final long lowThreshold = storage.getStorageLowBytes(
                        Environment.getDataDirectory());

                //返回:-1 计算安装包大小有错误
                //返回其他:安装包大小。
                final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(
                        origin.resolvedPath, packageAbiOverride);
                if (sizeBytes >= 0) {
                    try {
                        //用于权限提升。
                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 00);
                        pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                                origin.resolvedPath, installFlags, packageAbiOverride);
                    } catch (InstallerException e) {
                        Slog.w(TAG, "Failed to free cache", e);
                    }
                }

                /*
                 * 缓存删除了我们下载安装的文件。
                 * 用于存储错误
                 */

                if (pkgLite.recommendedInstallLocation
                        == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                    pkgLite.recommendedInstallLocation
                            = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
                }
            }


            //安装返回码
            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                //指定推荐的安装位置。 可以是其中之一
                //RECOMMEND_INSTALL_INTERNAL 安装在内部存储上,
                //RECOMMEND_INSTALL_EXTERNAL 安装在外部媒体上,
                //RECOMMEND_FAILED_INSUFFICIENT_STORAGE 用于存储错误,
                //或 RECOMMEND_FAILED_INVALID_APK 解析错误。
                int loc = pkgLite.recommendedInstallLocation;
                ...
            }

            //创建安装参数
            final InstallArgs args = createInstallArgs(this);
            mVerificationCompleted = true;
            mIntegrityVerificationCompleted = true;
            mEnableRollbackCompleted = true;
            mArgs = args;

            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                final int verificationId = mPendingVerificationToken++;

                // 执行安装包验证(除非我们只是简单地移动装包)。
                if (!origin.existing) {
                    ...
                }


                //INSTALL_ENABLE_ROLLBACK 的标志参数以指示应为此安装启用回滚。
                if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
                    // TODO(ruhler) b/112431924: 在“move”的情况下不要这样做?
                    final int enableRollbackToken = mPendingEnableRollbackToken++;
                    Trace.asyncTraceBegin(
                            TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
                    mPendingEnableRollback.append(enableRollbackToken, this);

                    Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
                    enableRollbackIntent.putExtra(
                            PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
                            enableRollbackToken);
                    enableRollbackIntent.putExtra(
                            PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
                            mSessionId);
                    enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
                    enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                    //允许在启动完成前发送广播。 在早期启动中提交分阶段会话的 apk 部分时需要这样做。 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。
                    // 在早期启动中提交分阶段会话的 apk 部分时需要这样做。
                    // 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。
                    enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

                    mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,
                            android.Manifest.permission.PACKAGE_ROLLBACK_AGENT,
                            new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                    // 等待回滚启用的持续时间,以毫秒为单位
                                    long rollbackTimeout = DeviceConfig.getLong(
                                            DeviceConfig.NAMESPACE_ROLLBACK,
                                            PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
                                            DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);
                                    if (rollbackTimeout < 0) {
                                        rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;
                                    }
                                    final Message msg = mHandler.obtainMessage(
                                            ENABLE_ROLLBACK_TIMEOUT);
                                    msg.arg1 = enableRollbackToken;
                                    msg.arg2 = mSessionId;
                                    mHandler.sendMessageDelayed(msg, rollbackTimeout);
                                }
                            }, null0nullnull);

                    mEnableRollbackCompleted = false;
                }
            }

            mRet = ret;
        }
        @Override
        void handleReturnCode() {
            if (mVerificationCompleted
                    && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
                //INSTALL_DRY_RUN :installPackage 的标志参数,指示只应验证包而不应安装包。
                if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
                    ...
                }
                if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                    //注释1
                    mRet = mArgs.copyApk();
                }
                //注释2
                processPendingInstall(mArgs, mRet);
            }
        }
    }
    }

注释1:mArgs 其实就是 InstallArgs ,而 InstallArgs 则是通过 createInstallArgs(this); 创建如下代码: createInstallArgs(this)

    private InstallArgs createInstallArgs(InstallParams params) {
        if (params.move != null) {
            //处理现有已安装应用程序移动的逻辑。
            return new MoveInstallArgs(params);
        } else {
            //处理新应用程序安装的逻辑,包括复制和重命名逻辑。
            return new FileInstallArgs(params);
        }
    }

正常的流程下,createInstallArgs 返回的是 FileInstallArgs 对象。

FileInstallArgs.copyApk()

拷贝部分

    class FileInstallArgs extends InstallArgs {
        private File codeFile;
        private File resourceFile;

        // Example topology:
        // /data/app/com.example/base.apk
        // /data/app/com.example/split_foo.apk
        // /data/app/com.example/lib/arm/libfoo.so
        // /data/app/com.example/lib/arm64/libfoo.so
        // /data/app/com.example/dalvik/arm/base.apk@classes.dex

        /** New install */
        FileInstallArgs(InstallParams params) {
            super(params);
        }

        /** Existing install */
        FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
            super(OriginInfo.fromNothing(), nullnull0, InstallSource.EMPTY,
                    nullnull, instructionSets, nullnullnull, MODE_DEFAULT, null0,
                    PackageParser.SigningDetails.UNKNOWN,
                    PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
                    falsenull /* parent */, DataLoaderType.NONE);
            this.codeFile = (codePath != null) ? new File(codePath) : null;
            this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
        }

        //执行此处方法
        int copyApk() {
            try {
                //就调用个doCopyApk(),接着往下看
                return doCopyApk();
            } finally {
            }
        }

        private int doCopyApk() {
            //表示文件已下载
            if (origin.staged) {
                ...
                if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
                //获取安装包路径
                codeFile = origin.file;
                resourceFile = origin.file;
                return PackageManager.INSTALL_SUCCEEDED;
            }

            try {
                final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
                //创建路径
                final File tempDir =
                        mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
                codeFile = tempDir;
                resourceFile = tempDir;
            } catch (IOException e) {
                Slog.w(TAG, "Failed to create copy file: " + e);
                return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
            }

            //将包复制到目标位置(origin.file.getAbsolutePath())。
            //返回状态码。注释3
            int ret = PackageManagerServiceUtils.copyPackage(
                    origin.file.getAbsolutePath(), codeFile);
            if (ret != PackageManager.INSTALL_SUCCEEDED) {
                Slog.e(TAG, "无法复制安装包");
                return ret;
            }

            final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());
            final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
            NativeLibraryHelper.Handle handle = null;
            try {
                handle = NativeLibraryHelper.Handle.create(codeFile);
                // 将 apk 中的动态库 .so 文件也拷贝到目标路径中。
                ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                        abiOverride, isIncremental);
            } catch (IOException e) {
                Slog.e(TAG, "Copying native libraries failed", e);
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
            } finally {
                IoUtils.closeQuietly(handle);
            }

            return ret;
        }
    }

注释3:PackageManagerServiceUtils.copyPackage() 这个看名字 就是调用 工具类 的 copyPackage 方法拷贝安装包。具体咱们看代码:

PackageManagerServiceUtils.copyPackage()

frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java

    /**
     * 将包复制到目标位置。
     * @param packagePath 要复制的包的绝对路径。 
     * 可以是单个单一的 APK 文件,也可以是包含一个或多个 APK 的集群目录。
     * @return 根据PackageManager 中的状态返回状态码
     */

    public static int copyPackage(String packagePath, File targetDir) {
        if (packagePath == null) {
            return PackageManager.INSTALL_FAILED_INVALID_URI;
        }

        try {
            final File packageFile = new File(packagePath);
            final PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0);
            //下面有copyFile的源码,咱一起看
            copyFile(pkg.baseCodePath, targetDir, "base.apk");
            if (!ArrayUtils.isEmpty(pkg.splitNames)) {
                for (int i = 0; i < pkg.splitNames.length; i++) {
                    copyFile(pkg.splitCodePaths[i], targetDir,
                            "split_" + pkg.splitNames[i] + ".apk");
                }
            }
            return PackageManager.INSTALL_SUCCEEDED;
        } catch (PackageParserException | IOException | ErrnoException e) {
            Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
        }
    }

    private static void copyFile(String sourcePath, File targetDir, String targetName)
            throws ErrnoException, IOException 
{
        if (!FileUtils.isValidExtFilename(targetName)) {
            throw new IllegalArgumentException("Invalid filename: " + targetName);
        }
        Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);

        final File targetFile = new File(targetDir, targetName);
        final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
                O_RDWR | O_CREAT, 0644);
        Os.chmod(targetFile.getAbsolutePath(), 0644);
        FileInputStream source = null;
        try {
            source = new FileInputStream(sourcePath);
            //将 source.getFD() 的内容复制到targetFd。
            //FileUtils:frameworks/base/core/java/android/os/FileUtils.java
            FileUtils.copy(source.getFD(), targetFd);
        } finally {
            IoUtils.closeQuietly(source);
        }
    }

看到这里 最终安装包在 data/app 目录下以 base.apk 的方式保存(例如:/data/app/com.example/base.apk),至此安装包拷贝工作就已经完成。

InstallParams

接下来咱们看看 InstallParams 中 的 注释2 processPendingInstall(mArgs, mRet); 也就是装载部分。

    class InstallParams extends HandlerParams {
        ...
        @Override
        void handleReturnCode() {
            if (mVerificationCompleted
                    && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
                ...
                if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                    //注释1
                    mRet = mArgs.copyApk();
                }                
                //注释2
                processPendingInstall(mArgs, mRet);
            }
        }
    }
    }

processPendingInstall()

装载部分

    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        //分包
        if (args.mMultiPackageInstallParams != null) {
            args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
        } else {
            //
            PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
            //异步操作,因为包安装可能需要一段时间。
            processInstallRequestsAsync(
                    res.returnCode == PackageManager.INSTALL_SUCCEEDED,
                    Collections.singletonList(new InstallRequest(args, res)));
        }
    }

下面咱看看他的异步操作。

processInstallRequestsAsync()

    private void processInstallRequestsAsync(boolean success,
            List<InstallRequest> installRequests)
 
{
        mHandler.post(() -> {
            if (success) {
                for (InstallRequest request : installRequests) {
                     // 预安装操作,主要是检查安装包的状态,确保安装环境正常,如果安装环境有问题会清理拷贝文件
                    request.args.doPreInstall(request.installResult.returnCode);
                }
                synchronized (mInstallLock) {
                    //真正的安装阶段
                    installPackagesTracedLI(installRequests);
                }
                for (InstallRequest request : installRequests) {
                    request.args.doPostInstall(
                            request.installResult.returnCode, request.installResult.uid);
                }
            }
            for (InstallRequest request : installRequests) {
                restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                        new PostInstallData(request.args, request.installResult, null));
            }
        });
    }

installPackagesTracedLI()

    @GuardedBy({"mInstallLock""mLock"})
    private void installPackagesTracedLI(List<InstallRequest> requests) {
        try {
            //添加跟踪 Trace。
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
            //调用 installPackageLI 方法进行安装。咱们接着看
            installPackagesLI(requests);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

installPackagesLI()

    @GuardedBy("mInstallLock")
    private void installPackagesLI(List<InstallRequest> requests) {
        ...
        boolean success = false;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                final PrepareResult prepareResult;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    //注释1
                    //成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
                    prepareResult =
                            preparePackageLI(request.args, request.installResult);
                } catch (PrepareFailure prepareFailure) {
                    ...
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                ...
            }
        }
    }

注释1:preparePackageLI() 包含内容过多咱们开始逐步讲解。

preparePackageLI()

    @GuardedBy("mInstallLock")
    private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
            throws PrepareFailure 
{
        final int installFlags = args.installFlags;
        final File tmpPackageFile = new File(args.getCodePath());
        final boolean onExternal = args.volumeUuid != null;
        final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
        final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
        final boolean virtualPreload =
                ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
        @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
        ...
        
        ParsedPackage parsedPackage;
        //PackageParser2:PackageParser 的 v2 用于在服务中启动解析时使用,并且必须包含服务包含的状态。
        try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
                mPackageParserCallback)) {
            // 注释1:pp.parsePackage()新包解析
            parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
            AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
        } catch (PackageParserException e) {
            throw new PrepareFailure("Failed parse during installPackageLI", e);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        ...

        try {
            // 要么使用我们得到的,要么直接从APK解析
            if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
                parsedPackage.setSigningDetails(args.signingDetails);
            } else {
                parsedPackage.setSigningDetails(
                        ParsingPackageUtils.getSigningDetails(parsedPackage, false /* skipVerify */));
            }
        } catch (PackageParserException e) {
            throw new PrepareFailure("Failed collect during installPackageLI", e);
        }

        //未使用v2签名
        if (instantApp && parsedPackage.getSigningDetails().signatureSchemeVersion
                < SignatureSchemeVersion.SIGNING_BLOCK_V2) {
            ...
        }

        boolean systemApp = false;
        boolean replace = false;
        synchronized (mLock) {
            // 检查是否已安装现有软件包
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            ...
              }
      
            PackageSetting ps = mSettings.mPackages.get(pkgName);
            if (ps != null) {
                if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);

                // 将签名与最新库版本的包设置进行比较。
                PackageSetting signatureCheckPs = ps;
                if (parsedPackage.isStaticSharedLibrary()) {
                    ...
                }

                //注释2:快速校验安装包签名
                final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
                    if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                                + parsedPackage.getPackageName() + " upgrade keys do not match the "
                                + "previously installed version");
                    }
                } else {
                    ...
                }

                if (ps.pkg != null) {
                    systemApp = ps.pkg.isSystem();
                }
                res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
            }


            // 注释3:设置相关权限,生成、移植权限 
            int N = ArrayUtils.size(parsedPackage.getPermissions());
            for (int i = N - 1; i >= 0; i--) {
                final ParsedPermission perm = parsedPackage.getPermissions().get(i);
                final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName());

                ...
            }
        }
        if (args.move != null) {
            // 我们进行了就地移动,因此 dex 已准备就绪
            ...
        } else {
            // 启用 SCAN_NO_DEX 标志以在稍后阶段跳过 dexopt
            scanFlags |= SCAN_NO_DEX;

            try {
                final boolean extractNativeLibs = !AndroidPackageUtils.isLibrary(parsedPackage);
                PackageSetting pkgSetting;
                synchronized (mLock) {
                    pkgSetting = mSettings.getPackageLPr(pkgName);
                }
                // 注释4:生成安装包Abi(Application binary interface,应用二进制接口)
                String abiOverride =
                        (pkgSetting == null || TextUtils.isEmpty(pkgSetting.cpuAbiOverrideString)
                        ? args.abiOverride : pkgSetting.cpuAbiOverrideString);
                boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
                        && pkgSetting.getPkgState().isUpdatedSystemApp();
                AndroidPackage oldPackage = mPackages.get(pkgName);
                boolean isUpdatedSystemAppInferred = oldPackage != null && oldPackage.isSystem();
                final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
                        derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage,
                        isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
                        abiOverride, extractNativeLibs);
                derivedAbi.first.applyTo(parsedPackage);
                derivedAbi.second.applyTo(parsedPackage);
            } catch (PackageManagerException pme) {
                Slog.e(TAG, "Error deriving application ABI", pme);
                throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
                        "Error deriving application ABI");
            }
        }
        //注释5:冻结 安装包
        final PackageFreezer freezer =
                freezePackageForInstall(pkgName, installFlags, "installPackageLI");
        boolean shouldCloseFreezerBeforeReturn = true;
        try {
            final AndroidPackage existingPackage;
            String renamedPackage = null;
            boolean sysPkg = false;
            int targetScanFlags = scanFlags;
            int targetParseFlags = parseFlags;
            final PackageSetting ps;
            final PackageSetting disabledPs;
            if (replace) {
                //更新包
                ...
            } else { 
                // 新包安装
                ...
            }
            // 解冻 安装包
            shouldCloseFreezerBeforeReturn = false;

            //返回成功准备好的安装包所需的数据集。
            return new PrepareResult(replace, targetScanFlags, targetParseFlags,
                    existingPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
                    ps, disabledPs);
        } finally {
            res.freezer = freezer;
            if (shouldCloseFreezerBeforeReturn) {
                freezer.close();
            }
        }
    }

咱再回来看 installPackagesLI()

installPackagesLI()

    @GuardedBy("mInstallLock")
    private void installPackagesLI(List<InstallRequest> requests) {
        ...
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
            for (InstallRequest request : requests) {
                final PrepareResult prepareResult;
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    //注释1
                    //成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
                    prepareResult =
                            preparePackageLI(request.args, request.installResult);
                ...
                try {
                    //扫描包并返回新解析的包。
                    //出现错误时返回null。
                    final ScanResult result = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user, request.args.abiOverride);
                    ...
                } catch (PackageManagerException e) {
                    request.installResult.setError("Scanning Failed.", e);
                    return;
                }
            }
            //包扫描结果和相关请求详细信息用于协调一个或多个包到系统的潜在添加。
            ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
                    installResults,
                    prepareResults,
                    mSharedLibraries,
                    Collections.unmodifiableMap(mPackages), versionInfos,
                    lastStaticSharedLibSettings);
            CommitRequest commitRequest = null;
            synchronized (mLock) {
                //ReconciledPackage:提交到内存中的数据结构和磁盘所需的所有数据的容器。
                //TODO:将此处包含的大部分数据移动到PackageSetting中进行提交。
                
                Map<String, ReconciledPackage> reconciledPackages;
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
                    reconciledPackages = reconcilePackagesLocked(
                            reconcileRequest, mSettings.mKeySetManagerService);
                } catch (ReconcileFailure e) {
                    for (InstallRequest request : requests) {
                        request.installResult.setError("Reconciliation failed...", e);
                    }
                    return;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
                    commitRequest = new CommitRequest(reconciledPackages,
                            mUserManager.getUserIds());
                    commitPackagesLocked(commitRequest);
                    success = true;
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
            }
            //注释2
            executePostCommitSteps(commitRequest);
        } finally {
            ...
        }
    }

注释2:这里有个 executePostCommitSteps() 方法,咱们一起来看看。

executePostCommitSteps()

    /**
     * 成功安装后,在提交完成并释放包锁后执行剩余步骤。 
     * 这些通常更昂贵或需要调用 installd,这通常会锁定 mLock。
     */

    private void executePostCommitSteps(CommitRequest commitRequest) {
        final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
        for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
            final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags
                            & PackageManagerService.SCAN_AS_INSTANT_APP) != 0);
            
            final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg;
            final String packageName = pkg.getPackageName();
            //注释1:安装并准备 APP 数据 
            prepareAppDataAfterInstallLIF(pkg);
            ...
            final boolean performDexopt =
                    (!instantApp || Global.getInt(mContext.getContentResolver(),
                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                    && !pkg.isDebuggable()
                    && (!onIncremental)
                    && dexoptOptions.isCompilationEnabled();

              //优化dex文件(实际为 dex2oat 操作,用来将 apk 中的 dex 文件转换为 oat 文件)
            if (performDexopt) {
                // Compile the layout resources.
                if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
                    mViewCompiler.compileLayouts(pkg);
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }

                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
                ScanResult result = reconciledPkg.scanResult;


                PackageSetting realPkgSetting = result.existingSettingCopied
                        ? result.request.pkgSetting : result.pkgSetting;
                if (realPkgSetting == null) {
                    realPkgSetting = reconciledPkg.pkgSetting;
                }

                // Unfortunately, the updated system app flag is only tracked on this PackageSetting
                boolean isUpdatedSystemApp = reconciledPkg.pkgSetting.getPkgState()
                        .isUpdatedSystemApp();

                realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);

                mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
                        null /* instructionSets */,
                        getOrCreateCompilerPackageStats(pkg),
                        mDexManager.getPackageUseInfoOrDefault(packageName),
                        dexoptOptions);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }

            // Notify BackgroundDexOptService that the package has been changed.
            // If this is an update of a package which used to fail to compile,
            // BackgroundDexOptService will remove it from its denylist.
            // TODO: Layering violation
            BackgroundDexOptService.notifyPackageChanged(packageName);

            notifyPackageChangeObserversOnUpdate(reconciledPkg);
        }
        NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
    }

咱们来看看 prepareAppDataAfterInstallLIF(pkg);

prepareAppDataAfterInstallLIF()

    /**
     * 在安装或升级后立即为给定的应用程序准备应用程序数据。 
     * 此方法仅会小心地接触为其安装的用户,并强制 restorecon 处理任何 seinfo 更改。
     * 
     * 验证目录是否存在以及所有已安装的应用程序的所有权和标签是否正确。
     * 如果所有权不匹配,它将尝试通过擦除数据来恢复系统应用程序; 第三方应用程序数据保持不变。
     * 
     * 注意:为了避免死锁,不要在持有mLock锁的情况下调用这个方法
     */

    private void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.mPackages.get(pkg.getPackageName());
            mSettings.writeKernelMappingLPr(ps);
        }

        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
        for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
            final int flags;
            if (umInternal.isUserUnlockingOrUnlocked(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)) {
                // TODO:这里是我们关注的。咱们接着看
                prepareAppDataLIF(pkg, user.id, flags);

                if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                    // 在外部存储上准备应用程序数据;
                    // 目前这用于设置由安装程序正确创建的任何 OBB 目录。
                    int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
                    smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
                }
            }
        }
    }
    

在这里看看 prepareAppDataLIF()

prepareAppDataLIF()

    private void prepareAppDataLIF(AndroidPackage pkg, int userId, int flags) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!"new Throwable());
            return;
        }
        prepareAppDataLeafLIF(pkg, userId, flags);
    }

prepareAppDataLeafLIF()

    private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
        if (DEBUG_APP_DATA) {
            Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x"
                    + Integer.toHexString(flags));
        }

        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.mPackages.get(pkg.getPackageName());
        }
        final String volumeUuid = pkg.getVolumeUuid();
        final String packageName = pkg.getPackageName();

        final int appId = UserHandle.getAppId(pkg.getUid());

        String pkgSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);

        Preconditions.checkNotNull(pkgSeInfo);

        final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : "");
        long ceDataInode = -1;
        try {
            ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                    appId, seInfo, pkg.getTargetSdkVersion());
        } catch (InstallerException e) {
            if (pkg.isSystem()) {
                logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
                        + ", but trying to recover: " + e);
                destroyAppDataLeafLIF(pkg, userId, flags);
                try {
                    //注释1: 最终调用 系统服务 Installer 安装
                    ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                            appId, seInfo, pkg.getTargetSdkVersion());
                    logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
                } catch (InstallerException e2) {
                    logCriticalInfo(Log.DEBUG, "Recovery failed!");
                }
            } else {
                Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e);
            }
        }
        
        if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) {
            mArtManagerService.prepareAppProfiles(pkg, userId,
                /* updateReferenceProfileContent= */ false);
        }

        if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
            // TODO: mark this structure as dirty so we persist it!
            synchronized (mLock) {
                if (ps != null) {
                    ps.setCeDataInode(ceDataInode, userId);
                }
            }
        }

        prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
    }

注释1:mInstaller

    // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
    // LOCK HELD.  Can be called with mInstallLock held.
    @GuardedBy("mInstallLock")
    final Installer mInstaller;

咱们看看 Installer

Installer

public class Installer extends SystemService {
    ...
    private volatile IInstalld mInstalld;
    public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo, int targetSdkVersion)
 throws InstallerException 
{
        if (!checkBeforeRemote()) return -1;
        try {
            return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                    targetSdkVersion);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }  
    ...
}

最终调用 系统服务 Installer 安装

至此整个 apk 的安装过程结束,实际上安装成功之后,还会发送一个 App 安装成功的广播 ACTION_PACKAGE_ADDED。手机桌面应用注册了这个广播,当接收到应用安装成功之后,就将 apk 的启动 icon 显示在桌面上。

流程图

帅次

2021/10/27  阅读:20  主题:自定义主题1

作者介绍

帅次

公众号:帅次