android应用市场点击下载APK安装详解

 Android系统启动篇

1,《android系统启动流程简介》

2,《android init进程启动流程》

3,《android zygote进程启动流程》

4,《Android SystemServer进程启动流程》

5,《android launcher启动流程》

6,《Android Activity启动过程详解》

Android系统开发准备篇

1,《Android 源码下载和编译》

2,《android 11源码编译和pixel3 刷机》

3,《Android Framework代码IDE加载和调试》

Android系统开发实践篇

1,《android设置默认输入法》

2,《android framework预制APK应用》

3,《Android系统层面限制应用开机自启动详解》

4,《android单独编译framework模块并push》

5,《Android Framework开发系统问题分析》

Android系统开发核心知识储备篇

1,《Android编译系统-envsetup和lunch代码篇》

2,《Android编译系统-概念篇》

3,《android日志系统详解》

4,《Android系统Handler详解》

5,《Android系统Binder详解》

6,《Android中Activity、View和Window关系详解》

7,《android view绘制流程详解》

8,《Android读取系统属性详解》

9,《android 窗口管理机制详解》

10,《初识Android系统》

11,《android中AMS进程通知Zygote进程fork新进程的通信方式》

Android核心功能详解篇

1,《android应用市场点击下载APK安装详解》

2,《Android 手势导航(从下往上滑动进入多任务页面)》

3,《android手势分析(应用界面左往右边滑动退出应用)》

4,《android应用安装流程详解》

5,《android11安装应用触发桌面图标刷新流程》

6,《Android系统多任务Recents详解》

7,《android系统导航栏视图分析》

———————————————————————————————————————————

目录

一,背景介绍

二,安装过程

2.1 流程概述

2.2 PackageInstaller安装APK

2.3 PMS执行安装


一,背景介绍

android的APK安装流程,有四种安装方式:

1,系统应用和预制应用安装,开机时完成,没有安装界面,在PKMS的构造函数中欧冠完成安装

2,网络下载应用安装,通过应用商店来完成,调用PackageManager.installPackages(),有安装界面

3,ADB工具安装,没有安装界面,它通过启动pm脚本的形式,然后调用com.android.commands.pm.Pm类,之后调用到PMS.installStage()完成安装

4,第三方应用安装,通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面.

均是通过PackageInstallObserver来监听安装是否成功。

二,安装过程

2.1 流程概述

应用安装主要流程:

1,将APK的信息通过IO流的形式写入到PackageInstaller.Session中。
2,调用PackageInstaller.Session的commit方法,将APK的信息交由PKMS处理。
3,拷贝APK
4,最后进行安装

        在应用市场点击一个未安装的apk后,发送广播打开PackageInstallerActivity,拉起com.android.packageinstaller(断点的进程)应用,弹出安装界面,这个主要是由bindUi构成,点击之后就会调用startInstall()进行安装。

/PackageInstallerActivity.java
private void bindUi() {
        mAlert.setIcon(mAppSnippet.icon);
        mAlert.setTitle(mAppSnippet.label);
        mAlert.setView(R.layout.install_content_view);
        mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
                (ignored, ignored2) -> {
                    if (mOk.isEnabled()) {
                        if (mSessionId != -1) {
                            mInstaller.setPermissionsResult(mSessionId, true);
                            finish();
                        } else {
                          //进行APK安装
                            startInstall();
                        }
                    }
                }, null);
        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
                (ignored, ignored2) -> {
                    // Cancel and finish
                    setResult(RESULT_CANCELED);
                    if (mSessionId != -1) {
                      //如果mSessionId存在,执行setPermissionsResult()完成取消安装
                        mInstaller.setPermissionsResult(mSessionId, false);
                    }
                    finish();
                }, null);
        setupAlert();

       ......
    }

//点击”安装“,跳转 InstallInstalling - 开始安装
private void startInstall() {
    // Start subactivity to actually install the application
    Intent newIntent = new Intent();
    newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
    newIntent.setData(mPackageURI);
    newIntent.setClass(this, InstallInstalling.class);
    String installerPackageName = getIntent().getStringExtra( Intent.EXTRA_INSTALLER_PACKAGE_NAME);
    ...
    if (installerPackageName != null) {
        newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
    }
    newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
    startActivity(newIntent);
    finish();
}

其中,R.layout.install_content_view布局视图如下:

        在startInstall方法组装了一个Intent,并跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity。在InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。

2.2 PackageInstaller安装APK

在启动InstallInstalling后,进入onCreate方法:

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

        ApplicationInfo appInfo = getIntent()
                .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
        mPackageURI = getIntent().getData();

          ......
            setupAlert();
            requireViewById(R.id.installing).setVisibility(View.VISIBLE);

            if (savedInstanceState != null) {
                mSessionId = savedInstanceState.getInt(SESSION_ID);
                mInstallId = savedInstanceState.getInt(INSTALL_ID);

                try {
                  //.根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的
                    InstallEventReceiver.addObserver(this, mInstallId,
                            this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    // Does not happen
                }
            } else {
                ......

                File file = new File(mPackageURI.getPath());
                try {
                    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) {
                    Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
                    Log.e(LOG_TAG,
                            "Cannot calculate installed size " + file + ". Try only apk size.");
                    params.setSize(file.length());
                } catch (IOException e) {
                    Log.e(LOG_TAG,
                            "Cannot calculate installed size " + file + ". Try only apk size.");
                    params.setSize(file.length());
                }

                try {
                  //向InstallEventReceiver注册一个观察者返回一个新的mInstallId,
                  //其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。
                    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();
        }
    }

        在onCreate中通过PackageInstaller通过创建Session并返回mSesionId,接着会在onResume中,会开启InstallingAsynTask,把包信息写入mSessionId对应的session,然后提交。

//InstallInstalling
protected void onResume() {
        super.onResume();

        // This is the first onResume in a single life of the activity
        if (mInstallingTask == null) {
            PackageInstaller installer = getPackageManager().getPackageInstaller();
          //获取sessionInfo
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

            if (sessionInfo != null && !sessionInfo.isActive()) {
              //创建内部类InstallingAsyncTask的对象,调用execute(),最终进入onPostExecute()
                mInstallingTask = new InstallingAsyncTask();
                mInstallingTask.execute();
            } else {
                // we will receive a broadcast when the install is finished
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            }
        }
    }

  private final class InstallingAsyncTask extends AsyncTask<Void, Void,
            PackageInstaller.Session> {
              
    @Override
    protected PackageInstaller.Session doInBackground(Void... params) {
        
              PackageInstaller.Session session;
            try {
                session = getPackageManager().getPackageInstaller().openSession(mSessionId);
            } catch (IOException e) {
                return null;
            }

            session.setStagingProgress(0);

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

                try (InputStream in = new FileInputStream(file)) {
                    long sizeBytes = file.length();
                  //从session中获取输出流
                    try (OutputStream out = session
                            .openWrite("PackageInstaller", 0, sizeBytes)) {
                        byte[] buffer = new byte[1024 * 1024];
                       ......
                    }
                }

                return session;
            } catch (IOException | SecurityException e) {
               ......
        }

        @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);
                                //包写入session进行提交
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

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

        在InstallingAsyncTask的doInBackground()里会根据包的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中,最后会在onPostExecute()中调用PackageInstaller.Session的commit方法,进行安装。

        在里面会看到一个PackageInstaller,也就是APK安装器,其实在ApplicationPackageManager的getPackageInstaller中创建的:

//ApplicationPackageManager
@Override
    public PackageInstaller getPackageInstaller() {
        synchronized (mLock) {
            if (mInstaller == null) {
                try {
                    mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
                            mContext.getPackageName(), getUserId());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return mInstaller;
        }
    }

        在这里会传入mPM.getPackageInstaller(),也就是IpacageInstaller的实例,其具体实现也就是PackageInstallerService, 其通过IPC的方式。它在初始化的时候会读取/data/system目录下的install_sessions文件,这个文件保存了系统未完成的Install Session。PMS则会根据文件的内容创建PackageInstallerSession对象并从插入到mSessions中。

//PackageInstallerService.java
 public PackageInstallerService(Context context, PackageManagerService pm,
            Supplier<PackageParser2> apexParserSupplier) {
        mContext = context;
        mPm = pm;
        mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);

        mInstallThread = new HandlerThread(TAG);
        mInstallThread.start();

        mInstallHandler = new Handler(mInstallThread.getLooper());

        mCallbacks = new Callbacks(mInstallThread.getLooper());

        mSessionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
                "package-session");
   //这个文件保存了系统未完成的`Install Session`
        mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
        mSessionsDir.mkdirs();

        mApexManager = ApexManager.getInstance();
        mStagingManager = new StagingManager(this, context, apexParserSupplier);
    }

        再来看下Session,是在于mSeesionId绑定的安装会话,代表着一个在进行中的安装。Session类是对IPackageInstaller.openSession(sessionId) 获取的 PackageInstallerSession(系统服务端)的封装。

        Session的创建和打开 具体实现是在 PackageInstallerService中,主要是 初始化apk的安装信息及环境,并创建一个sessionId,将安装Session与sessionId 进行绑定.

        接着我们回到InstallingAsyncTask中,在这里调用了session.commit方法:

//PackageInstaller        
public void commit(@NonNull IntentSender statusReceiver) {
            try {
              //调用PackageInstallerSession的commit方法,进入到java框架层
                mSession.commit(statusReceiver, false);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

//PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
                ......
          //如果尚未调用,则会话将被密封。此方法可能会被多次调用以更新状态接收者验证调用者权限
        if (!markAsSealed(statusReceiver, forTransfer)) {
            return;
        }
        //不同的包
        if (isMultiPackage()) {
            final SparseIntArray remainingSessions = mChildSessionIds.clone();
            final IntentSender childIntentSender =
                    new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
                            .getIntentSender();
            boolean sealFailed = false;
            for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
                final int childSessionId = mChildSessionIds.keyAt(i);
                // seal all children, regardless if any of them fail; we'll throw/return
                // as appropriate once all children have been processed
                if (!mSessionProvider.getSession(childSessionId)
                        .markAsSealed(childIntentSender, forTransfer)) {
                    sealFailed = true;
                }
            }
            if (sealFailed) {
                return;
            }
        }
        dispatchStreamValidateAndCommit();
}

private void dispatchStreamValidateAndCommit() {
        mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
    }
mSession的类型为IPackageInstallerSession,这说明要通过IPackageInstallerSession来进行进程间的通信,最终会调用PackageInstallerSession的commit方法。
在这里发送了一个MSG_STREAM_VALIDATE_AND_COMMIT的信号,并在handler中进行处理:
public boolean handleMessage(Message msg) {
        case MSG_STREAM_VALIDATE_AND_COMMIT:
           handleStreamValidateAndCommit();
           break;
            case MSG_INSTALL:
                handleInstall(); //
                break;
        ......
}

    private void handleStreamValidateAndCommit() {
        ......
            if (unrecoverableFailure != null) {
                onSessionVerificationFailure(unrecoverableFailure);
                // fail other child sessions that did not already fail
                for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
                    PackageInstallerSession session = nonFailingSessions.get(i);
                    session.onSessionVerificationFailure(unrecoverableFailure);
                }
            }
        }

        if (!allSessionsReady) {
            return;
        }

        mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
    }
在handleStreamValidateAndCommit又发送了消息MSG_INSTALL,实际上真正在执行的是在handleInstall中:
private void handleInstall() {
        ......

        // 对于 multiPackage 会话,请在锁之外读取子会话,因为在持有锁的情况下读取子会话可能会导致死锁 (b123391593)。
        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);
        }
    }

private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
            throws PackageManagerException {
        ......
            if (!success) {
                sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
                        isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
                        failure.error, failure.getLocalizedMessage(), null);
                return;
            }
            mPm.installStage(installingChildSessions);
        } else {
            mPm.installStage(installingSession);
        }
    }

        最后执行到了PMS的installStage方法。在上述的过程中,通过PackageInstaller维持了Session,把安装包写入到Session,真正的安装过程就要来看PMS了。

2.3 PMS执行安装

//PackageManagerService.java
void installStage(List<ActiveInstallSession> children)
            throws PackageManagerException {
  //创建了类型未INIT_COPY的消息
        final Message msg = mHandler.obtainMessage(INIT_COPY);
  //创建InstallParams,它对应于包的安装数据
        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));
  //将InstallParams通过消息发送出去
        mHandler.sendMessage(msg);
    }

handler对INIT_COPY的消息进行处理:

//PackageManagerService.java
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");
                      //执行APK拷贝动作
                        params.startCopy();
                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                    }
                    break;
                }
                ......
            }
  
  final void startCopy() {
            if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
            handleStartCopy();
            handleReturnCode();
        }

        在这里调用了两个方法handleStartCopy和handleReturnCode,其实现是在InstallParams 中。
在handleStartCopy,做了以下操作:

  • 检查空间大小,如果空间不够则释放无用空间
  • 覆盖原有安装位置的文件,并根据返回结果来确定函数的返回值,并设置installFlags
  • 确定是否有任何已安装的包验证器,如有,则延迟检测。主要分三步:首先新建一个验证Intent,然后设置相关的信息,之后获取验证器列表,最后向每个验证器发送验证Intent
public void handleStartCopy() {
  ......
    //解析包 返回最小的细节:pkgName、versionCode、安装所需空间大小、获取安装位置等
    pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                    origin.resolvedPath, installFlags, packageAbiOverride);
  ......
    //覆盖原有安装位置的文件,并根据返回结果来确定函数的返回值,并设置installFlags。
    if (ret == PackageManager.INSTALL_SUCCEEDED) {
                int loc = pkgLite.recommendedInstallLocation;
                if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
                    ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_URI;
                } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
                    ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
                } else {
                     .......
                }
            }
  
  //安装参数
  final InstallArgs args = createInstallArgs(this);
            mVerificationCompleted = true;
            mIntegrityVerificationCompleted = true;
            mEnableRollbackCompleted = true;
            mArgs = args;

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

                // apk完整性校验
                if (!origin.existing) {
                    PackageVerificationState verificationState =
                            new PackageVerificationState(this);
                    mPendingVerification.append(verificationId, verificationState);

                    sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
                    ret = sendPackageVerificationRequest(
                            verificationId, pkgLite, verificationState);

                    ......
                }

}

然后来看下handleReturnCode方法:

@Override
        void handleReturnCode() {
            ......
                if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                  //执行APKcopy拷贝
                    mRet = mArgs.copyApk();
                }
          //执行安装
                processPendingInstall(mArgs, mRet);
            }
        }

APK的copy过程是如何拷贝的:

//packageManagerService.java
int copyApk() {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
            try {
                return doCopyApk();
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

private int doCopyApk() {
            ......

            int ret = PackageManagerServiceUtils.copyPackage(
                    origin.file.getAbsolutePath(), codeFile);
            ......
            return ret;
        }
//继续追踪下去,他会到PackagemanagerSeriveUtils的copyFile方法

//PackagemanagerSeriveUtils
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);
            FileUtils.copy(source.getFD(), targetFd);
        } finally {
            IoUtils.closeQuietly(source);
        }
    }

        在这里就通过文件流的操作,把Apk拷贝到/data/app的目录下了。结束完拷贝之后,就要进入真正的安装了,流程如下:

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

//排队执行异步操作
private void processInstallRequestsAsync(boolean success,
            List<InstallRequest> installRequests) {
        mHandler.post(() -> {
            if (success) {
                for (InstallRequest request : installRequests) {
                  //进行检验,如果之前安装失败,则清除无用信息
                    request.args.doPreInstall(request.installResult.returnCode);
                }
                synchronized (mInstallLock) {
                  //安装的核心方法,进行解析apk安装
                    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,接着内部执行到了installPackagesLI方法:

//PackageMmanagerSerice.java 
private void installPackagesLI(List<InstallRequest> requests) {
   .......
     //分析当前任何状态,分析包并对其进行初始化验证
     prepareResult =
          preparePackageLI(request.args, request.installResult);
      
  ......
    //根据准备阶段解析包的信息上下文,进一步解析
      final ScanResult result = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user, request.args.abiOverride);     
    .......
      //验证扫描后包的信息好状态,确保安装成功
      reconciledPackages = reconcilePackagesLocked(
                            reconcileRequest, mSettings.mKeySetManagerService);
          
        //提交所有的包并更新系统状态。这是安装流中唯一可以修改系统状态的地方,必须在此阶段之前确定所有可预测的错误
        commitRequest = new CommitRequest(reconciledPackages,
                            mUserManager.getUserIds());
                    commitPackagesLocked(commitRequest);
  .......
    //完成APK安装
  executePostCommitSteps(commitRequest);
 }

由上面代码可知,installPackagesLI主要做了以下事情:

  • 分析当前任何状态,分析包并对其进行初始化验证
  • 根据准备阶段解析包的信息上下文,进一步解析
  • 验证扫描后包的信息好状态,确保安装成功
  • 提交所有骚哦欧庙的包并更新系统状态
  • 完成APK安装

在 preparePackageLI() 内使用 PackageParser2.parsePackage() 解析AndroidManifest.xml,获取四大组件等信息;使用ParsingPackageUtils.getSigningDetails() 解析签名信息;重命名包最终路径 等。

完成了解析和校验准备工作后,最后一步就是对apk的安装了。这里调用了executePostCommitSteps准备app数据,并执行dex优化。

//PackageManagerService.java
private void executePostCommitSteps(CommitRequest commitRequest) {
  //进行安装
  prepareAppDataAfterInstallLIF(pkg);
   .......
   final boolean performDexopt =
                    (!instantApp || Global.getInt(mContext.getContentResolver(),
                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                    && !pkg.isDebuggable()
                    && (!onIncremental);
  
  //为新的代码路径准备应用程序配置文件
  mArtManagerService.prepareAppProfiles(
                    pkg,
                    resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
  
  if (performDexopt) {

             ......
               //其中分配了 dexopt 所需的库文件
               PackageSetting realPkgSetting = result.existingSettingCopied
                        ? result.request.pkgSetting : result.pkgSetting;
                if (realPkgSetting == null) {
                    realPkgSetting = reconciledPkg.pkgSetting;
                }
                
                            //执行dex优化
                mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
                        null /* instructionSets */,
                        getOrCreateCompilerPackageStats(pkg),
                        mDexManager.getPackageUseInfoOrDefault(packageName),
                        dexoptOptions);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
}

在prepareAppDataAfterInstallLIF方法中,经过一系列的调用,最中会调用到 mInstaller.createAppData,这里也是调用Installd守护进程的入口:

public class Installer extends SystemService {
    
   @Override
    public void onStart() {
        if (mIsolated) {
            mInstalld = null;
        } else {
          //通过Binder调用到进程installd
            connect();
        }
    }

    private void connect() {
        IBinder binder = ServiceManager.getService("installd");
        ......

        if (binder != null) {
            mInstalld = IInstalld.Stub.asInterface(binder);
            try {
                invalidateMounts();
            } catch (InstallerException ignored) {
            }
        } else {
            Slog.w(TAG, "installd not found; trying again");
            BackgroundThread.getHandler().postDelayed(() -> {
                connect();
            }, DateUtils.SECOND_IN_MILLIS);
        }
    }
  
     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);
        }
    }
    }

可以看到最终调用了Installd的createAppData方法进行安装。Installer是Java层提供的Java API接口,Installd 则是在init进程启动的具有root权限的Daemon进程。

在processInstallRequestsAsync最后一步时调用了restoreAndPostInstall,在安装完成时会发送POST_INSTALL消息:

//PackageManagerService.java
private void restoreAndPostInstall(
            int userId, PackageInstalledInfo res, @Nullable PostInstallData data) {
  
  .......
    if (!doRestore) {
            
            if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);

            Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
            mHandler.sendMessage(msg);
        }
}

void doHandleMessage(Message msg) {
  .......
  case POST_INSTALL: {
    .......
      //处理安装结果
    handlePackagePostInstall(parentRes, grantPermissions,
                                killApp, virtualPreload, grantedPermissions,
                                whitelistedRestrictedPermissions, autoRevokePermissionsMode,
                                didRestore, args.installSource.installerPackageName, args.observer,
                                args.mDataLoaderType);
  }
}

private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
            boolean killApp, boolean virtualPreload,
            String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
            int autoRevokePermissionsMode,
            boolean launchedForRestore, String installerPackage,
            IPackageInstallObserver2 installObserver, int dataLoaderType) {
  
  ......
    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                        extras, 0 /*flags*/,
                        null /*targetPackage*/, null /*finishedReceiver*/,
                        updateUserIds, instantUserIds, newBroadcastWhitelist);
}

最后发送了ACTION_PACKAGE_ADDED广播,launcher接收到这个广播之后就会在桌面上添加应用图标了。

猜你喜欢

转载自blog.csdn.net/allen_xu_2012_new/article/details/130770012