PMS (PackageManagerService) is the core of the Android package management mechanism and is responsible for managing packages. PMS APP installation process - Get APK file: Before installing the application, you need to get the APK file. The APK file is the installation package of the Android application, which contains the application code and resource files.
- Parsing APK files: PMS needs to parse APK files to obtain application information and component information, such as application package name, version number, permission list, component list (such as Activity, Service, Receiver, etc.). This step is usually completed by the PackageParser class.
- Verify application signature: Before installation, PMS will verify the application signature to ensure that the application has not been tampered with or disguised. Signature verification is an important step to ensure application security.
- Install the application: If the verification passes, PMS will assign a UID to the application and continue the installation process. This usually involves steps such as file copying and processing installation parameters.
File Copying PackageManagerService.java#installStage installation stage: - Creates an InstallParams object
- Creates and sends an INIT_COPY message.
- InstallParams inherits from HandlerParams and is used to record the parameters of installing the application.
There is a member variable mArgs in InstallParams, which is an abstract type InstallArgs, mainly used to perform APK copying. The actual implementation class includes FileInstallArgs to complete the installation of non-ASEC applications. The full name of ASEC is Android Secure External Cache, and MoveInstallArgs is used to complete the mobile installation of installed applications. void installStage(String packageName, File stagedDir, String stagedCid, IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams, String installerPackageName, int installerUid, UserHandle user, Certificate[][] certificates) { ... 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, certificates, installReason); params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; ... //发送信息拷贝INIT_COPY 信息mHandler.sendMessage(msg); } PackageManagerService.java#PackageHandler package processing: connectToService() The service used to check and copy removable files sends MCS_BOUND information, triggering the processing of the first installation request. void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params); //mBound用于标识是否绑定了服务,默认值为false if (!mBound) { Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); //connectToService里面的DefaultContainerService是用于检查和复制可移动文件的服务if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); if (params.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } //绑定服务失败则return return; } else { //绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理mPendingInstalls.add(idx, params); } } else { //已经绑定服务mPendingInstalls.add(idx, params); if (idx == 0) { //5 //发送MCS_BOUND类型的消息,触发处理第一个安装请求mHandler.sendEmptyMessage(MCS_BOUND); } } break; .... } } MCS_BOUND process processing: case MCS_BOUND: if (mContainerService == null) { //判断是否已经绑定了服务if (!mBound) { //绑定服务的标识位,没有绑定成功Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params)); if (params.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } return; } //绑定失败,清空安装请求队列mPendingInstalls.clear(); } else { // 绑定成功//继续等待绑定服务Slog.w(TAG, "Waiting to connect to media container service"); } } else if (mPendingInstalls.size() > 0) { //安装APK的队列HandlerParams params = mPendingInstalls.get(0); //安装队列有参数if (params != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params)); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy"); if (params.startCopy()) { //HandlerParams开始拷贝if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..."); //如果APK安装成功,删除本次安装请求if (mPendingInstalls.size() > 0) { mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { //安装队列没有参数if (mBound) { //已经绑定服务,需要发送一个解绑MCS_UNBIND的message //如果没有安装请求了,发送解绑服务的请求if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND"); removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); sendMessageDelayed(ubmsg, 10000); } } else { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work"); //如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求mHandler.sendEmptyMessage(MCS_BOUND); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }else { Slog.w(TAG, "Empty queue"); } break; DefaultContainerService: The class that actually handles copying APP files PackageManagerService.java#HandlerParams#startCopy starts copying: - Whether the number of installation attempts exceeds 4 times, if it exceeds, the installation list data will be removed
- handleStartCopy: //Copy APK file
- handleReturnCode: //Start installing APK
final boolean startCopy() { boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); //startCopy方法尝试的次数,超过了4次,就放弃这个安装请求if (++mRetries > MAX_RETRIES) { Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); mHandler.sendEmptyMessage(MCS_GIVE_UP); //发送放弃安装信息handleServiceError(); return false; } else { handleStartCopy(); //复制APK文件res = true; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT"); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } handleReturnCode(); //处理复制APK后的安装APK逻辑return res; } } PackageManagerService.java#InstallParams#handleStartCopy copy apk file: - Get some installation information of APP
- Get the installation location of the APP
- InstallArgs Copy APP----> FileInstallArgs Copy APP----> DefaultContainerService Copy APP
InstallArgs is an abstract class. FileInstallArgs and MoveInstallArgs inherit InstallArgs. FileInstallArgs is for data/data/package name (system application), and MoveInstallArgs is used to handle the movement of installed APK: public void handleStartCopy() throws RemoteException { ... //确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装) 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) { // APK不能同时安装在SD卡和Data分区Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; //安装标志冲突,Instant Apps不能安装到SD卡中} else if (onSd && ephemeral) { Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { //获取APK的少量的信息pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); if (DEBUG_EPHEMERAL && ephemeral) { Slog.v(TAG, "pkgLite for install: " + pkgLite); } ... 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 { loc = installLocationPolicy(pkgLite); //确定APP安装的位置... } } //根据InstallParams创建InstallArgs对象final InstallArgs args = createInstallArgs(this); InstallArgs作用时:复制和重命名APK mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { ... if (!origin.existing && requiredUid != -1 && isVerificationEnabled(verifierUser.getIdentifier(), installFlags, installerUid)) { ... } else{ ret = args.copyApk(mContainerService, true); // InstallArgs开始复制APP } } mRet = ret; } private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { ... try { final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; //创建临时文件存储目录final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); codeFile = tempDir; resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } ... int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); ... return ret; } Install APK - Before installation, check whether the environment is reliable. If it is not reliable, the copied APK file will be cleared.
- installPackageTracedLI will call the installPackageLI method of PMS internally to install the APP.
- Process post-installation operations. If the installation is unsuccessful, delete the installation-related directories and files.
final boolean startCopy() { ...... handleStartCopy(); //APP文件复制拷贝..... //开始安装APP handleReturnCode(); } void handleReturnCode() { ........ if (mArgs != null) { processPendingInstall(mArgs, mRet); } } private void processPendingInstall(final InstallArgs args, final int currentStatus) { mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); 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); } ... } }); } |