一讲到APK安装流程,它有四种安装方式:
- 系统应用和预制应用安装,开机时完成,没有安装界面,在PKMS的构造函数中欧冠完成安装
- 网络下载应用安装,通过应用商店来完成,调用PackageManager.installPackages(),有安装界面
- ADB工具安装,没有安装界面,它通过启动pm脚本的形式,然后调用com.android.commands.pm.Pm类,之后调用到PMS.installStage()完成安装
- 第三方应用安装,通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面.
均是通过PackageInstallObserver来监听安装是否成功。
下面我们通过点击下载应用安装来了解安装的过程:
先说个大概:
1.将APK的信息通过IO流的形式写入到PackageInstaller.Session中。2.调用PackageInstaller.Session的commit方法,将APK的信息交由PKMS处理。3.拷贝APK4.最后进行安装
在点击一个未安装的apk后,会弹出安装界面,点击确定按钮后,会进入PackageInstallerActivity界面,后面会触发bindUi方法,弹出底部安装界面。这个主要是由bindUi构成,上面会有取消和安装两个按钮,点击之后就会调用startInstall()进行安装。
//PackageInstallerActivity.javaprivate 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();}
在startInstall方法组装了一个Intent,并跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity。在InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。
2.1 PackageInstaller安装APK
在启动InstallInstalling后,进入onCreate方法:
//InstallInstallingprotected 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,然后提交。
//InstallInstallingprotected 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 { @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 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.javapublic 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 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 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.2 PMS执行安装
/PackageManagerService.javavoid installStage(List 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.javavoid 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.javaint 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方法//PackagemanagerSeriveUtilsprivate 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.javaprivate 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 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 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.javaprivate 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.javaprivate 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 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接收到这个广播之后就会在桌面上添加应用图标了。