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 finishsetResult(RESULT_CANCELED);if (mSessionId != -1) {//如果mSessionId存在,执行setPermissionsResult()完成取消安装mInstaller.setPermissionsResult(mSessionId, false);}finish();}, null);setupAlert();......}//点击”安装“,跳转 InstallInstalling - 开始安装
private void startInstall() {// Start subactivity to actually install the applicationIntent 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方法来创建并返回mSessionIdmSessionId = 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 activityif (mInstallingTask == null) {PackageInstaller installer = getPackageManager().getPackageInstaller();//获取sessionInfoPackageInstaller.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 finishedmCancelButton.setEnabled(false);setFinishOnTouchOutside(false);}}}private final class InstallingAsyncTask extends AsyncTask<Void, Void,PackageInstaller.Session> {@Overrideprotected 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) {......}@Overrideprotected 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
@Overridepublic 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.javapublic 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 processedif (!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 failfor (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方法:
@Overridevoid 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 {@Overridepublic void onStart() {if (mIsolated) {mInstalld = null;} else {//通过Binder调用到进程installdconnect();}}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接收到这个广播之后就会在桌面上添加应用图标了。