android 安装应用过程

PMS 在创建的时候创建了PackageInstallerService,所以在安装应用之前先了解一下 PackageInstallerService :用于管理安装的服务

附带的是 Android 9.0 的源码

管理会话的服务 - PackageInstallerService

  • PackageInstallerService 主要用于管理安装会话服务,可以通过 PackageInstallerService 分配一个 SessionId,这个系统唯一的安装 id 代表一次安装过程,如果一个应用安装需要几个步骤完成,即使设备重启了,也可以通过这个ID继续完成安装。
  • PackageInstallerService 中提供了 createSession() 创建一个 Session
    @Override
    public int createSession(SessionParams params, String installerPackageName, int userId) {
        try {
            return createSessionInternal(params, installerPackageName, userId);
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
    }

createSession() 将会返回一个系统唯一值作为 Session ID 。如果希望再次使用这个 Session ID 可以同过 openSession() 去打开它;

    @Override
    public IPackageInstallerSession openSession(int sessionId) {
        try {
            return openSessionInternal(sessionId);
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
    }

openSession() 返回一个 IPackageInstallerSession 对象,它是 Binder 服务 PackageInstallerSession 的 IBinder 对象。每一个 Install Session 都会在 SystemServer 中有一个对应的 PackageInstallerSession 对象。在 PackageInstallerService 中的 mSessions 数组中保存了所有 PackageInstallerSession 对象

private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
  • 在系统初始化的时候,PMS会创建 PackageInstallerService 服务,在创建这个服务时,会读取 /data/system/ 目录下的 install_session.xml 文件
mSessionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
                "package-session");

这个文件中保存了系统中未完成的 Install Session 。然后PackageInstallerService 会通过文件内容创建 PackageInstallerSession对象并插入到 mSessions 中。PackageInstallerSession 中保存了应用安装的相关数据如路径、进度、中间数据保存等。

	// 解析 xml 文件
  private void writeSessionsLocked() {
        FileOutputStream fos = null;
        try {
            fos = mSessionsFile.startWrite();

            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_SESSIONS);
            final int size = mSessions.size();
            for (int i = 0; i < size; i++) {
            // 创建 PackageInstallerSession 对象
                final PackageInstallerSession session = mSessions.valueAt(i);
                // 通过 session 写入
                session.write(out, mSessionsDir);
            }
            out.endTag(null, TAG_SESSIONS);
            out.endDocument();

            mSessionsFile.finishWrite(fos);
        } catch (IOException e) {
            if (fos != null) {
                mSessionsFile.failWrite(fos);
            }
        }
    }

安装应用的开端

  • 在 android 中,通过发送 Intent 就可以启动安装应用流程。
	Intent intent = new Intent(Intent.ACTION_VIEW);
	intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
	context.startActivity(intent);
  • 在 android 系统应用 PackageInstaller 中有一个 PackageInstallerActivity 会响应这个 Intent。在这个 Activity 中有两个很重要的成员变量 PackageManager mPm; 和 PackageInstaller mInstaller; 分别是 ApplicationPackageManager 和 PackageInstaller 的实例对象。这两个对象也是 PackageManagerService 和 PackageInstallerService 的代理对象。创建这两个对象的方法如下:
    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(null);
        mPm = getPackageManager();
        mInstaller = mPm.getPackageInstaller();
  }
  • 点击确认安装按钮后会执行 startInstall()
    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 (mOriginatingURI != null) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
        }
        if (mReferrerURI != null) {
            newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
        }
        if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
        }
        if (installerPackageName != null) {
            newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                    installerPackageName);
        }
        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
        }
        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
        startActivity(newIntent);
        finish();
    }
  • 上面的代码跳转到了 InstallInstalling.class ,它也是一个 Activity

首先看它的 onCreate() 方法,主要是创建了 sessionId,其中取消按钮的点击事件mInstallingTask ,是在 onResume() 中创建的,所以接下来后看一下 onResume 的代码。

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

        setContentView(R.layout.install_installing);

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

        if ("package".equals(mPackageURI.getScheme())) {
            try {
                // 如果是 package 直接调用 installExistingPackage 
                // installExistingPackage 会调用到 PMS 的 mPm.installExistingPackageAsUser()
                getPackageManager().installExistingPackage(appInfo.packageName);
                launchSuccess();
            } catch (PackageManager.NameNotFoundException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        } else {
            // 如果是 file
            final File sourceFile = new File(mPackageURI.getPath());
            PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
                    sourceFile), R.id.app_snippet);

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

                // Reregister for result; might instantly call back if result was delivered while
                // activity was destroyed
                try {
                    InstallEventReceiver.addObserver(this, mInstallId,
                            this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    // Does not happen
                }
            } else {
                // 获取参数
                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                params.installFlags = PackageManager.INSTALL_FULL_APP;
                params.referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
                params.originatingUri = getIntent()
                        .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
                params.originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
                        UID_UNKNOWN);
                params.installerPackageName =
                        getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);

                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 {
                    mInstallId = InstallEventReceiver
                            .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                    this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }

                try {
                    // 创建 SessionId 这是安装的唯一id 存储到 mSessions集合中,如果安装失败还可以通过id 继续之前未完成的安装
                    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
                } catch (IOException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }
            }

            mCancelButton = (Button) findViewById(R.id.cancel_button);

            mCancelButton.setOnClickListener(view -> {
            // mInstallingTask 是在 onResume() 中创建的,所以下面会看一下 onResume() 的代码,看看task执行的是谁什么内容
                if (mInstallingTask != null) {
                    mInstallingTask.cancel(true);
                }

                if (mSessionId > 0) {
                    getPackageManager().getPackageInstaller().abandonSession(mSessionId);
                    mSessionId = 0;
                }

                setResult(RESULT_CANCELED);
                finish();
            });

            mSessionCallback = new InstallSessionCallback();
        }
    }
  • InstallInstalling.class 的 onResume()
    @Override
    protected void onResume() {
        super.onResume();

        // This is the first onResume in a single life of the activity
        if (mInstallingTask == null) {
            // getPackageInstaller() 返回的是 PackageInstallerService
            PackageInstaller installer = getPackageManager().getPackageInstaller();
            // 通过唯一id mSessionId 获取安装信息 ;onCreate 中创建的mSessionId 存储到了installer 的 mSessions数组中
            // 通过 getSessionInfo 获取信息如果获取不到就直接cancel了
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
            if (sessionInfo != null && !sessionInfo.isActive()) {
                // 创建 InstallingAsyncTask 
                mInstallingTask = new InstallingAsyncTask();
                // 执行 mInstallingTask
                mInstallingTask.execute();
            } else {
                // we will receive a broadcast when the install is finished
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            }
        }
    }

onResume() 方法中,继续下一步安装是执行了 InstallingAsyncTask.execute() 接下来看一下这个 task;

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

        @Override
        protected PackageInstaller.Session doInBackground(Void... params) {
            PackageInstaller.Session session;
            try {
                // 通过 openSession() 获取保存的 session信息 如果获取不到安装结束
                session = getPackageManager().getPackageInstaller().openSession(mSessionId);
            } catch (IOException e) {
                return null;
            }

            session.setStagingProgress(0);

            try {
                // 将file信息 通过流写入到 PackageInstaller.Session session; 中
                File file = new File(mPackageURI.getPath());

                try (InputStream in = new FileInputStream(file)) {
                    long sizeBytes = file.length();
                    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;
                            }

                            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(
                        getPackageManager().getPermissionControllerPackageName());
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallInstalling.this,
                        mInstallId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
				// 这句是重点会调用到 PackageInstallerSession 的 commit方法 
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }
    }
  • 上一步的 task 会调用到 PackageInstallerSession 的 commit 方法
    @Override
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
        Preconditions.checkNotNull(statusReceiver);

        final boolean wasSealed;
        synchronized (mLock) {
            // 。。。。
            mActiveCount.incrementAndGet();

            mCommitted = true;
            // 最后发送了 handler 信息
            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
        }
  • 接收 MSG_COMMIT 的 handler 方法
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
             	// ... 
                case MSG_COMMIT:
                    synchronized (mLock) {
                        try {
                            commitLocked();
                        } catch (PackageManagerException e) {
                            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
                            Slog.e(TAG,
                                    "Commit of session " + sessionId + " failed: " + completeMsg);
                            destroyInternal();
                            dispatchSessionFinished(e.error, completeMsg, null);
                        }
                    }
                    break;
               // .....
            }

            return true;
        }
    };

commitLocked 方法最后调用了下面这句话

private final PackageManagerService mPm;
private void commitLocked() throws PackageManagerException {
	// ...
	mPm.installStage(mPackageName, stageDir, localObserver, params,
                mInstallerPackageName, mInstallerUid, user, mSigningDetails);
}

安装逻辑就走到了 PackageManagerService 的 installStage() 方法,后面的安装就和 PMS有关了

应用安装的第一阶段-复制文件

  • 接下来继续从 installStage() 方法开始
void installStage(String packageName, File stagedDir,
            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
            String installerPackageName, int installerUid, UserHandle user,
            PackageParser.SigningDetails signingDetails) {
		// ... 
	    final Message msg = mHandler.obtainMessage(INIT_COPY);
        final int installReason = fixUpInstallReason(installerPackageName, installerUid,
                sessionParams.installReason);
        final InstallParams params = new InstallParams(origin, null, observer,
                sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                verificationInfo, user, sessionParams.abiOverride,
                sessionParams.grantedRuntimePermissions, signingDetails, installReason);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;
		// mHandler 发送了 INIT_COPY 信息 携带了安装的参数 InstallParams
        mHandler.sendMessage(msg);
}
  • mHandler 接收的消息
case INIT_COPY: {
					// 获取参数
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (!mBound) {
                    	// connectToService 连接成功会把 mBound 设置成 true
                    	// 绑定 service 成功后也会发送  mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            params.serviceError();
                            return;
                        } else {
                        	// 绑定服务成功把安装信息保存到 mPendingInstalls
                        	// 待收到连接信息返回后继续安装
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                  		// 之后再接收到信息就直接添加到 mPendingInstalls 
                        mPendingInstalls.add(idx, params);
                        // Already bound to the service. Just make
                        // sure we trigger off processing the first request.
                        if (idx == 0) {
                        	// mPendingInstalls 如果只有一个则立刻发出 MCS_BOUND 消息
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }
  • 接下来看 handler 收到了 MCS_BOUND 消息后是怎么处理的;
                case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                        mContainerService = (IMediaContainerService) msg.obj;
                    }
                    // 如果 mContainerService == null 是异常情况
                    if (mContainerService == null) {
                        if (!mBound) {
                            for (HandlerParams params : mPendingInstalls) {
                                // Indicate service bind error
                                // 通知回调者出错了
                                params.serviceError();
                            }
                            mPendingInstalls.clear();
                        } else {
                            Slog.w(TAG, "Waiting to connect to media container service");
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        // 上一步添加到了 mPendingInstalls 中,判断如果有数据
                        // 取出安装数据
                        HandlerParams params = mPendingInstalls.get(0);
                        if (params != null) {
                            // 执行安装操作
                            if (params.startCopy()) {
                                // We are done...  look for more work or to go idle.
                                // Delete pending install
                                // 工作完成删除列表第一项
                                if (mPendingInstalls.size() > 0) {
                                    mPendingInstalls.remove(0);
                                }
                                // 判断是否还有未完成的任务 size == 0 代表没有未完成的任务
                                if (mPendingInstalls.size() == 0) {
                                    // mBound 是在连接service的时候设置的true 如果false说明service未绑定
                                    if (mBound) {
                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                                "Posting delayed MCS_UNBIND");
                                        removeMessages(MCS_UNBIND);
                                        Message ubmsg = obtainMessage(MCS_UNBIND);
                                        // 如果没有安装信息并且 sergice 已经绑定,延迟发送一个解绑信息
                                        sendMessageDelayed(ubmsg, 10000);
                                    }
                                } else {
                                    // 如果还有未完成的任务,则再次发送 MCS_BOUND ,取出头信息继续startCopy() 操作
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                        }
                    } else {
                        // 代表没有要执行的任务 也就是 mPendingInstalls 队列中没有数据
                    }
                    break;
                }
  • 接下来看 params.startCopy() 是如何操作的
        final boolean startCopy() {
            boolean res;
            try {
                // private static final int MAX_RETRIES = 4; 
                // 如果重试 4 次还未成功则退出 
                if (++mRetries > MAX_RETRIES) {
                    // 发送 MCS_GIVE_UP 消息
                    mHandler.sendEmptyMessage(MCS_GIVE_UP);
                    handleServiceError();
                    return false;
                } else {
                    // 执行安装 startCopy() 方法也会捕获 handleStartCopy 内部抛出的异常 进行重连等操作
                    handleStartCopy();
                    res = true;
                }
            } catch (RemoteException e) {
                // 安装出错 发送消息重新连接
                mHandler.sendEmptyMessage(MCS_RECONNECT);
                res = false;
            }
            handleReturnCode();
            return res;
        }

startCopy() 将会调用 handleStartCopy(); 来完成安装操作。startCopy() 主要是进行错误处理,捕获到 handleStartCopy 抛出异常以后,将会发送 MCS_RECONNECT 消息进行重新绑定 service,绑定成功会重新安装流程,startCopy() 将会再次调用,重试次数超过4次将安装失败。如果成功将会调用 handleReturnCode();继续处理。

  • handleStartCopy() 方法
public void handleStartCopy() throws RemoteException {
            int ret = PackageManager.INSTALL_SUCCEEDED;
            // If we're already staged, we've firmly committed to an install location
            if (origin.staged) {
                if (origin.file != null) {
                    // 记录安装位置的标志
                    installFlags |= PackageManager.INSTALL_INTERNAL;
                    installFlags &= ~PackageManager.INSTALL_EXTERNAL;
                } else {
                    throw new IllegalStateException("Invalid stage location");
                }
            }
            // 是否安装在 sd 卡
            final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
            // 是否安装在内部
            final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
            // 表示轻量级的临时安装包
            final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
            PackageInfoLite pkgLite = null;

            if (onInt && onSd) {
                // 标记冲突:如果既安装到sd卡 又安装到内部 则安装失败 记录错误类型
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else if (onSd && ephemeral) {
                // 这个也是标记冲突 记录错误后结束
                Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else {
                // 获取关于安装包信息的 PackageInfoLite 对象
                pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                        packageAbiOverride);
                        // 下面这一段:如果安装空间不够 释放cache空间
                if (!origin.staged && pkgLite.recommendedInstallLocation
                        == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                    // TODO: focus freeing disk space on the target device
                    final StorageManager storage = StorageManager.from(mContext);
                    final long lowThreshold = storage.getStorageLowBytes(
                            Environment.getDataDirectory());

                    final long sizeBytes = mContainerService.calculateInstalledSize(
                            origin.resolvedPath, packageAbiOverride);

                    try {
                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
                        pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
                                installFlags, packageAbiOverride);
                    } catch (InstallerException e) {
                        Slog.w(TAG, "Failed to free cache", e);
                    }

                    /*
                     * The cache free must have deleted the file we
                     * downloaded to install.
                     *
                     * TODO: fix the "freeCache" call to not delete
                     *       the file we care about.
                     */
                    if (pkgLite.recommendedInstallLocation
                            == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                        pkgLite.recommendedInstallLocation
                            = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
                    }
                }
            }
            // ....
            // ....
            final InstallArgs args = createInstallArgs(this);
            mArgs = args;

            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                // TODO: http://b/22976637
                // Apps installed for "all" users use the device owner to verify the app
                UserHandle verifierUser = getUser();
                if (verifierUser == UserHandle.ALL) {
                    verifierUser = UserHandle.SYSTEM;
                }

                /*
                 * Determine if we have any installed package verifiers. If we
                 * do, then we'll defer to them to verify the packages.
                 */
                // 下面很长一段作用是应用的校验,做法是通过发送有校验功能的 intent 进行。
                final int requiredUid = mRequiredVerifierPackage == null ? -1
                        : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                                verifierUser.getIdentifier());
                final int installerUid =
                        verificationInfo == null ? -1 : verificationInfo.installerUid;
                if (!origin.existing && requiredUid != -1
                   		// ... 省略代码
                        /*
                         * We don't want the copy to proceed until verification
                         * succeeds, so null out this field.
                         */
                        mArgs = null;
                    }
                } else {
                    // 如果没有校验 则直接调用 copyApk 继续处理
                    ret = args.copyApk(mContainerService, true);
                }
            }
            mRet = ret;
        }

handleStartCopy() 的逻辑是先通过 getMinimalPackageInfo() 确定安装空间是否足够,并记录错误原因,如果安装空间不够则通过 mInstaller.freeCache() 释放空间。接下来调用 final InstallArgs args = createInstallArgs(this); 创建 InstallArgs 对象(InstallArgs 分为 AsecInstallArgs 和 FileInstallArgs)。接下来是很长一段应用的校验,然后调用args.copyApk 进行下一步操作。

        int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
            try {
                return doCopyApk(imcs, temp);
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

copyApk 调用了 doCopyApk() 代码如下:

        private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
            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;
                // 在 data/app 生成临时文件
                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;
            }
            // 为临时文件创建文件描述符,它可以通过 Binder 传递
            final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
                @Override
                public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
                    if (!FileUtils.isValidExtFilename(name)) {
                        throw new IllegalArgumentException("Invalid filename: " + name);
                    }
                    try {
                        final File file = new File(codeFile, name);
                        final FileDescriptor fd = Os.open(file.getAbsolutePath(),
                                O_RDWR | O_CREAT, 0644);
                        // 0644->即用户具有读写权限,组用户和其它用户具有只读权限;
                        Os.chmod(file.getAbsolutePath(), 0644);
                        return new ParcelFileDescriptor(fd);
                    } catch (ErrnoException e) {
                        throw new RemoteException("Failed to open: " + e.getMessage());
                    }
                }
            };

            int ret = PackageManager.INSTALL_SUCCEEDED;
            // 使用 DefaultContainerService  的 copyPackage 方法复制文件
            ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
            if (ret != PackageManager.INSTALL_SUCCEEDED) {
                Slog.e(TAG, "Failed to copy package");
                return ret;
            }
            // 安装应用自带native的动态库
            final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
            NativeLibraryHelper.Handle handle = null;
            try {
                handle = NativeLibraryHelper.Handle.create(codeFile);
                ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                        abiOverride);
            } catch (IOException e) {
                Slog.e(TAG, "Copying native libraries failed", e);
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
            } finally {
                IoUtils.closeQuietly(handle);
            }

            return ret;
        }

doCopyApk() 是调用了 DefaultContainerService 的 copyPackage() 方法复制文件到 /data/app 下,如果应用中还有动态库也会把 apk的动态库提取出来。
执行完这一步后 应用安装的第一步就结束了,应用被安装到了 /data/app 下

第二阶段-装载应用

  • 接下来是第二阶段的工作,把应用的格式转换成 ota 的格式,为应用创建数据目录,最后把应用的信息装载到 PackageManagerService 的数据结构中。

  • 前面最后走到了 doCopyApk() 方法,前面的调用连可以发现,startCopy 再走完copy 流程之后会调用 handleReturnCode(); 方法。

  • handleReturnCode();

        @Override
        void handleReturnCode() {
            if (mArgs != null) {
            	// 调用了 processPendingInstall 继续处理
                processPendingInstall(mArgs, mRet);
            }
        }
  • processPendingInstall() 方法
    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        // Queue up an async operation since the package installation may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                // 防止重复调用
                mHandler.removeCallbacks(this);
                 // Result object to be returned
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.setReturnCode(currentStatus);
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = null;
                // 判断是否安装成功
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    // 如果安装成功
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                        // 装载安装的应用
                        installPackageTracedLI(args, res);
                    }
                    args.doPostInstall(res.returnCode, res.uid);
                }

                // 下面一段是执行备份

                // ....
				
                if (!doRestore) {
                    // No restore possible, or the Backup Manager was mysteriously not
                    // available -- just fire the post-install work request directly.
                    if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
                    // 发送 POST_INSTALL 消息
                    Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                    mHandler.sendMessage(msg);
                }
            }
        });
    }

processPendingInstall() 方法中发送了一个 mHandler.post 异步消息,这样过程将以异步的方式执行,调用了 installPackageTracedLI(args, res); 来装载应用,然后执行了备份,最后发送了 POST_INSTALL 来继续处理。

  • installPackageTracedLI 方法
    private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
        final int installFlags = args.installFlags;
        final String installerPackageName = args.installerPackageName;
        final String volumeUuid = args.volumeUuid;
        final File tmpPackageFile = new File(args.getCodePath());
        final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
        final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
                || (args.volumeUuid != null));
        final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
        final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
        final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
        final boolean virtualPreload =
                ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
        boolean replace = false;
        @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
        if (args.move != null) {
            // moving a complete application; perform an initial scan on the new install location
            scanFlags |= SCAN_INITIAL;
        }
        if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
            scanFlags |= SCAN_DONT_KILL_APP;
        }
        if (instantApp) {
            scanFlags |= SCAN_AS_INSTANT_APP;
        }
        if (fullApp) {
            scanFlags |= SCAN_AS_FULL_APP;
        }
        if (virtualPreload) {
            scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
        }

        // Result object to be returned
        res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
        res.installerPackageName = installerPackageNa
        // Sanity check
        if (instantApp && (forwardLocked || onExternal)) {
            res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
            return;
        }

        // Retrieve PackageSettings and parse package
        // 创建 apk 文件解析器
        @ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
                | PackageParser.PARSE_ENFORCE_CODE
                | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
                | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
                | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
        PackageParser pp = new PackageParser();
        pp.setSeparateProcesses(mSeparateProcesses);
        pp.setDisplayMetrics(mMetrics);
        pp.setCallback(mPackageParserCallback);

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
        final PackageParser.Package pkg;
        try {
            // 解析 apk 文件
            pkg = pp.parsePackage(tmpPackageFile, parseFlags);
            DexMetadataHelper.validatePackageDexMetadata(pkg);
        } catch (PackageParserException e) {
            res.setError("Failed parse during installPackageLI", e);
            return;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }

        // Instant apps have several additional install-time checks.
        if (instantApp) {
            if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                        "Instant app package must target at least O");
                return;
            }
            if (pkg.applicationInfo.targetSandboxVersion != 2) {
                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                        "Instant app package must use targetSandboxVersion 2");
                return;
            }
            if (pkg.mSharedUserId != null) {
                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                        "Instant app package may not declare a sharedUserId");
                return;
            }
        }

        if (pkg.applicationInfo.isStaticSharedLibrary()) {
            // Static shared libraries have synthetic package names
            renameStaticSharedLibraryPackage(pkg);
            // No static shared libs on external storage
            if (onExternal) {
                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                        "Packages declaring static-shared libs cannot be updated");
                return;
            }
        }
        // If we are installing a clustered package add results for the children
        // 如果是安装集群包 则把子包的信息也解析存储
        if (pkg.childPackages != null) {
            synchronized (mPackages) {
                final int childCount = pkg.childPackages.size();
                for (int i = 0; i < childCount; i++) {
                    PackageParser.Package childPkg = pkg.childPackages.get(i);
                    PackageInstalledInfo childRes = new PackageInstalledInfo();
                    childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                    childRes.pkg = childPkg;
                    childRes.name = childPkg.packageName;
                    PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                    if (childPs != null) {
                        childRes.origUsers = childPs.queryInstalledUsers(
                                sUserManager.getUserIds(), true);
                    }
                    if ((mPackages.containsKey(childPkg.packageName))) {
                        childRes.removedInfo = new PackageRemovedInfo(this);
                        childRes.removedInfo.removedPackage = childPkg.packageName;
                        childRes.removedInfo.installerPackageName = childPs.installerPackageName;
                    }
                    if (res.addedChildPackages == null) {
                        res.addedChildPackages = new ArrayMap<>();
                    }
                    res.addedChildPackages.put(childPkg.packageName, childRes);
                }
            }
        }

        // If package doesn't declare API override, mark that we have an install
        // time CPU ABI override.
        if (TextUtils.isEmpty(pkg.cpuAbiOverride)) {
            pkg.cpuAbiOverride = args.abiOverride;
        }

        String pkgName = res.name = pkg.packageName;
        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
            if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
                res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
                return;
            }
        }
        // 收集应用签名
        try {
            // either use what we've been given or parse directly from the APK
            if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
                pkg.setSigningDetails(args.signingDetails);
            } else {
                PackageParser.collectCertificates(pkg, false /* skipVerify */);
            }
        } catch (PackageParserException e) {
            res.setError("Failed collect during installPackageLI", e);
            return;
        }

        if (instantApp && pkg.mSigningDetails.signatureSchemeVersion
                < SignatureSchemeVersion.SIGNING_BLOCK_V2) {
            Slog.w(TAG, "Instant app package " + pkg.packageName
                    + " is not signed with at least APK Signature Scheme v2");
            res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                    "Instant app package must be signed with APK Signature Scheme v2 or greater");
            return;
        }

        // Get rid of all references to package scan path via parser.
        pp = null;
        String oldCodePath = null;
        boolean systemApp = false;
        synchronized (mPackages) {
            // 判断是否是更新应用
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
                String oldName = mSettings.getRenamedPackageLPr(pkgName);
                if (pkg.mOriginalPackages != null
                        && pkg.mOriginalPackages.contains(oldName)
                        && mPackages.containsKey(oldName)) {
                    pkg.setPackageName(oldName);
                    pkgName = pkg.packageName;
                    replace = true; // true 代表替换升级应用
                } else if (mPackages.containsKey(pkgName)) {
                // true 代表替换升级应用
                    replace = true;
                }
                // Child packages are installed through the parent package
                if (pkg.parentPackage != null) {
                    return;
                }
                if (replace) {
                    // Prevent apps opting out from runtime permissions
                    PackageParser.Package oldPackage = mPackages.get(pkgName);
                    final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
                    final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
                    if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
                            && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                        return;
                    }
                    // Prevent persistent apps from being updated
                    if ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0) {
                        return;
                    }
                    // Prevent installing of child packages
                    if (oldPackage.parentPackage != null) {
                        return;
                    }
                }
            }

            PackageSetting ps = mSettings.mPackages.get(pkgName);
            if (ps != null) {
                PackageSetting signatureCheckPs = ps;
                if (pkg.applicationInfo.isStaticSharedLibrary()) {
                    SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
                    if (libraryEntry != null) {
                        signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
                    }
                }
                final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
                    if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
                        return;
                    }
                } else {
                    try {
                        final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                        final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
                        // We don't care about disabledPkgSetting on install for now.
                        final boolean compatMatch = verifySignatures(
                                signatureCheckPs, null, pkg.mSigningDetails, compareCompat,
                                compareRecover);
                        // The new KeySets will be re-added later in the scanning process.
                        if (compatMatch) {
                            synchronized (mPackages) {
                                ksms.removeAppKeySetDataLPw(pkg.packageName);
                            }
                        }
                    } catch (PackageManagerException e) {
                        res.setError(e.error, e.getMessage());
                        return;
                    }
                }

                oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
                if (ps.pkg != null && ps.pkg.applicationInfo != null) {
                    systemApp = (ps.pkg.applicationInfo.flags &
                            ApplicationInfo.FLAG_SYSTEM) != 0;
                }
                res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
            }
            // 检查应用中的 permission 是否已经被其他应用定义了
            // 如果重新定义的系统应用定义的 permission 则忽略本应用的定义 然后继续
            // 如果定义的是非系统应用定义的 permission 则本地安装失败
            int N = pkg.permissions.size();
            for (int i = N-1; i >= 0; i--) {
                final PackageParser.Permission perm = pkg.permissions.get(i);
                final BasePermission bp =
                        (BasePermission) mPermissionManager.getPermissionTEMP(perm.info.name);

                // Don't allow anyone but the system to define ephemeral permissions.
                if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
                        && !systemApp) {
                    Slog.w(TAG, "Non-System package " + pkg.packageName
                            + " attempting to delcare ephemeral permission "
                            + perm.info.name + "; Removing ephemeral.");
                    perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT;
                }

                // Check whether the newly-scanned package wants to define an already-defined perm
                if (bp != null) {
                    // If the defining package is signed with our cert, it's okay.  This
                    // also includes the "updating the same package" case, of course.
                    // "updating same package" could also involve key-rotation.
                    final boolean sigsOk;
                    final String sourcePackageName = bp.getSourcePackageName();
                    final PackageSettingBase sourcePackageSetting = bp.getSourcePackageSetting();
                    final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                    if (sourcePackageName.equals(pkg.packageName)
                            && (ksms.shouldCheckUpgradeKeySetLocked(
                                    sourcePackageSetting, scanFlags))) {
                        sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
                    } else {

                        // in the event of signing certificate rotation, we need to see if the
                        // package's certificate has rotated from the current one, or if it is an
                        // older certificate with which the current is ok with sharing permissions
                        if (sourcePackageSetting.signatures.mSigningDetails.checkCapability(
                                        pkg.mSigningDetails,
                                        PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
                            sigsOk = true;
                        } else if (pkg.mSigningDetails.checkCapability(
                                        sourcePackageSetting.signatures.mSigningDetails,
                                        PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {

                            // the scanned package checks out, has signing certificate rotation
                            // history, and is newer; bring it over
                            sourcePackageSetting.signatures.mSigningDetails = pkg.mSigningDetails;
                            sigsOk = true;
                        } else {
                            sigsOk = false;
                        }
                    }
                    if (!sigsOk) {
                        // If the owning package is the system itself, we log but allow
                        // install to proceed; we fail the install on all other permission
                        // redefinitions.
                        if (!sourcePackageName.equals("android")) {
                            res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package "
                                    + pkg.packageName + " attempting to redeclare permission "
                                    + perm.info.name + " already owned by " + sourcePackageName);
                            res.origPermission = perm.info.name;
                            res.origPackage = sourcePackageName;
                            return;
                        } else {
                            Slog.w(TAG, "Package " + pkg.packageName
                                    + " attempting to redeclare system permission "
                                    + perm.info.name + "; ignoring new declaration");
                            pkg.permissions.remove(i);
                        }
                    } else if (!PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) {
                        // Prevent apps to change protection level to dangerous from any other
                        // type as this would allow a privilege escalation where an app adds a
                        // normal/signature permission in other app's group and later redefines
                        // it as dangerous leading to the group auto-grant.
                        if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                                == PermissionInfo.PROTECTION_DANGEROUS) {
                            if (bp != null && !bp.isRuntime()) {
                                Slog.w(TAG, "Package " + pkg.packageName + " trying to change a "
                                        + "non-runtime permission " + perm.info.name
                                        + " to runtime; keeping old protection level");
                                perm.info.protectionLevel = bp.getProtectionLevel();
                            }
                        }
                    }
                }
            }
        }

        if (systemApp) {
            if (onExternal) {
                // 系统应用不允许安装在 sd 卡上
                // Abort update; system app can't be replaced with app on sdcard
                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                        "Cannot install updates to system apps on sdcard");
                return;
            } else if (instantApp) {
                // 系统应用不能被立刻更新
                // Abort update; system app can't be replaced with an instant app
                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                        "Cannot update a system app with an instant app");
                return;
            }
        }

        if (args.move != null) {
            // We did an in-place move, so dex is ready to roll
            scanFlags |= SCAN_NO_DEX;
            scanFlags |= SCAN_MOVE;

            synchronized (mPackages) {
                final PackageSetting ps = mSettings.mPackages.get(pkgName);
                if (ps == null) {
                    res.setError(INSTALL_FAILED_INTERNAL_ERROR,
                            "Missing settings for moved package " + pkgName);
                }

                // We moved the entire application as-is, so bring over the
                // previously derived ABI information.
                pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
                pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;
            }

        } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) {
            // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
            scanFlags |= SCAN_NO_DEX;

            try {
                String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
                    args.abiOverride : pkg.cpuAbiOverride);
                final boolean extractNativeLibs = !pkg.isLibrary();
                derivePackageAbi(pkg, abiOverride, extractNativeLibs);
            } catch (PackageManagerException pme) {
                Slog.e(TAG, "Error deriving application ABI", pme);
                res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
                return;
            }

            // Shared libraries for the package need to be updated.
            synchronized (mPackages) {
                try {
                    updateSharedLibrariesLPr(pkg, null);
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
                }
            }
        }

        if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
            res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
            return;
        }

        if (PackageManagerServiceUtils.isApkVerityEnabled()) {
            String apkPath = null;
            synchronized (mPackages) {=
                final PackageSetting ps = mSettings.mPackages.get(pkgName);
                if (ps != null && ps.isPrivileged()) {
                    apkPath = pkg.baseCodePath;
                }
            }

            if (apkPath != null) {
                final VerityUtils.SetupResult result =
                        VerityUtils.generateApkVeritySetupData(apkPath);
                if (result.isOk()) {
                    FileDescriptor fd = result.getUnownedFileDescriptor();
                    try {
                        final byte[] signedRootHash = VerityUtils.generateFsverityRootHash(apkPath);
                        mInstaller.installApkVerity(apkPath, fd, result.getContentSize());
                        mInstaller.assertFsverityRootHashMatches(apkPath, signedRootHash);
                    } catch (InstallerException | IOException | DigestException |
                             NoSuchAlgorithmException e) {
                        return;
                    } finally {
                        IoUtils.closeQuietly(fd);
                    }
                } else if (result.isFailed()) {
                    res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Failed to generate verity");
                    return;
                } else {
                }
            }
        }

        if (!instantApp) {
            startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
        } else {
        }

        try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
                "installPackageLI")) {
            if (replace) {
                // 如果安装的是升级包 调用 replacePackageLIF 继续处理
                if (pkg.applicationInfo.isStaticSharedLibrary()) {
                    PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
                    if (existingPkg != null &&
                            existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) {
                        res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
                                + "static-shared libs cannot be updated");
                        return;
                    }
                }
                replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
                        installerPackageName, res, args.installReason);
            } else {
                // 如果是新应用 调用 installNewPackageLIF 继续处理
                installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
                        args.user, installerPackageName, volumeUuid, res, args.installReason);
            }
        }

方法中解析了应用包,然后判断是升级应用调用了 replacePackageLIF() 还是新的应用 调用了 installNewPackageLIF()
下面看一下装载后发送的 POST_INSTALL 是怎么处理的

case POST_INSTALL: {
                    PostInstallData data = mRunningInstalls.get(msg.arg1);
                    final boolean didRestore = (msg.arg2 != 0);
                    mRunningInstalls.delete(msg.arg1);

                    if (data != null) {
                        InstallArgs args = data.args;
                        PackageInstalledInfo parentRes = data.res;

                        final boolean grantPermissions = (args.installFlags
                                & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
                        final boolean killApp = (args.installFlags
                                & PackageManager.INSTALL_DONT_KILL_APP) == 0;
                        final boolean virtualPreload = ((args.installFlags
                                & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
                        final String[] grantedPermissions = args.installGrantPermissions;

                        // Handle the parent package
                        // 调用了 handlePackagePostInstall  内部会判断是否安装成功,发送对应的 广播事件
                        // 通知其他应用进行处理 比如桌面添加图标等,并回调给安装者成功事件
                        handlePackagePostInstall(parentRes, grantPermissions, killApp,
                                virtualPreload, grantedPermissions, didRestore,
                                args.installerPackageName, args.observer);

                        // Handle the child packages
                        final int childCount = (parentRes.addedChildPackages != null)
                                ? parentRes.addedChildPackages.size() : 0;
                        for (int i = 0; i < childCount; i++) {
                            PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
                            // 如果是集群安装每个都会发送
                            handlePackagePostInstall(childRes, grantPermissions, killApp,
                                    virtualPreload, grantedPermissions, false /*didRestore*/,
                                    args.installerPackageName, args.observer);
                        }
                    }
                } break;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值