Android(安卓)PackageManagerService(二)下载安装详解
下载安装可分为两部分:拷贝应用和安装应用。拷贝过程的函数调用时序图如图2所示
下载安装frameworks层的入口函数为PackageManager.installPackage,由应用市场APP调用,然后调用PMS.installPackageAsUser,然后发送消息INIT_COPY、MCS_BOUND开始复制,调用HandlerParams.startCopy。这个方法主要分两部分,一部分是拷贝应用的执行程序,另一部分是创建应用的数据目录,拷贝部分由handleStartCopy完成。之后调用handlerReturnCode来处理创建数据目录。拷贝部分会调用DefaultContainerService来完成,该服务为那些可能位于可删除空间上的文件提供检查和拷贝功能。当底层设置被移除时,这样设计可以防止系统进程保留打开的文件时,不被内核杀死。
handleStartcopy实现在PMS内部类InstallParams中,它的功能是调用远程方法获取包信息和安装位置,下面我们结合关键代码做进一步分析。
@Override public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); final int callingUid = Binder.getCallingUid();//确认权限 enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");//adb安装 if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { installFlags |= PackageManager.INSTALL_FROM_ADB; } else { // Caller holds INSTALL_PACKAGES permission, so we're less strict // about installerPackageName. installFlags &= ~PackageManager.INSTALL_FROM_ADB; installFlags &= ~PackageManager.INSTALL_ALL_USERS; } UserHandle user;//所有用户 if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) { user = UserHandle.ALL; } else { user = new UserHandle(userId); } // Only system components can circumvent runtime permissions when installing.//权限校验 if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0 && mContext.checkCallingOrSelfPermission(Manifest.permission .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) { throw new SecurityException("You need the " + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission " + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag"); } if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0 || (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { throw new IllegalArgumentException( "New installs into ASEC containers no longer supported"); } final File originFile = new File(originPath); final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile); final Message msg = mHandler.obtainMessage(INIT_COPY); params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params)); msg.obj = params;//发送拷贝的消息 mHandler.sendMessage(msg); }
接收消息
//PackageHandler.doHandleMessage void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: { HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (!mBound) { //连接服务,当服务绑定好之后,会在发一个MCS_BOUND消息 if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); if (params.traceMethod != null) { } return; } else { 添加到任务队列 mPendingInstalls.add(idx, params); } } else { mPendingInstalls.add(idx, params); if (idx == 0) { //发送一个已经绑定的消息 mHandler.sendEmptyMessage(MCS_BOUND); } } break; }
接收MCS_BOUND消息
//PackageHandler.doHandleMessagecase MCS_BOUND: { if (msg.obj != null) { //获取服务 mContainerService = (IMediaContainerService) msg.obj; } if (mContainerService == null) { //如果没有绑定清空队列 if (!mBound) { for (HandlerParams params : mPendingInstalls) { params.serviceError(); return; } mPendingInstalls.clear(); } } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); if (params != null) { //调用startCopy if (params.startCopy()) { if (mPendingInstalls.size() > 0) { mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { if (mBound) { removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); sendMessageDelayed(ubmsg, 10000); } } else { mHandler.sendEmptyMessage(MCS_BOUND); } } } } break; }
获取HandlerParams 并调用startCopy
// [InstallParams.startCopy] final boolean startCopy() { boolean res; try { if (++mRetries > MAX_RETRIES) { mHandler.sendEmptyMessage(MCS_GIVE_UP); handleServiceError(); return false; } else { handleStartCopy(); res = true; } } catch (RemoteException e) { mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } handleReturnCode(); return res; }
尝试处理4次,如果成功调用handleReturnCode,否则返回错误。
接下来进入InstallParams.handleStartCopy方法看一下。
// [InstallParams.handleStartCopy]public void handleStartCopy() throws RemoteException { int ret = PackageManager.INSTALL_SUCCEEDED; // 首先检查文件和cid是否已生成,如生成则设置installFlags。 if (origin.staged) { if (origin.file != null) { installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } else if (origin.cid != null) { installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else { throw new IllegalStateException("Invalid stage location"); } }//在sd卡 final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;//在内部存储 final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;//免安装app final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; PackageInfoLite pkgLite = null; if (onInt && onSd) { ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else if (onSd && ephemeral) { ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); /* * 然后检查空间大小,如果空间不够则释放无用空间。 */ if (!origin.staged && pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { // TODO: 集中释放目标设备上的磁盘空间 final StorageManager storage = StorageManager.from(mContext);//最小临界值 final long lowThreshold = storage.getStorageLowBytes( Environment.getDataDirectory());//计算所需空间的大小 final long sizeBytes = mContainerService.calculateInstalledSize( origin.resolvedPath, isForwardLocked(), 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); } } }//覆盖原有安装位置的文件,并根据返回结果来确定函数的返回值,并设置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 { // 更具安装策略获取安装位置 loc = installLocationPolicy(pkgLite); if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) { ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; } else if (!onSd && !onInt) { // Override install location with flags if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { // Set the flag to install on external media. installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag"); } installFlags |= PackageManager.INSTALL_INSTANT_APP; installFlags &= ~(PackageManager.INSTALL_EXTERNAL |PackageManager.INSTALL_INTERNAL); } else { // Make sure the flag for installing on external // media is unset installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } } } }//创建安装参数 final InstallArgs args = createInstallArgs(this); mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { //确定我们是否安装了包验证器。如果我们这样做,那么我们将遵从他们来验证软件包。 final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); final int installerUid = verificationInfo == null ? -1 : verificationInfo.installerUid;....省略包验证,一般安装不走这个流程....确定是否有任何已安装的包验证器,如有,则延迟检测。主要分三步:首先新建一个验证Intent,然后设置相关的信息,之后获取验证器列表,最后向每个验证器发送验证Intent。 /* *没有启用包验证,因此立即启动远程调用,使用临时文件初始化复制。 */ ret = args.copyApk(mContainerService, true); } mRet = ret; }
向验证器客户端发送intent,只有当验证成功之后才会开启copy工作。如果没有任何验证器则直接拷贝。
接着调用InstallArgs.copyApk方法,手机内部存储安装子类为FileInstallArgs
//FileInstallArgs.copyApkint copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { try { return doCopyApk(imcs, temp); } finally { }}////FileInstallArgs.doCopyApkprivate int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { //如果已经确定位置直接返回if (origin.staged) {codeFile = origin.file;resourceFile = origin.file;return PackageManager.INSTALL_SUCCEEDED;}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;}final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {@Overridepublic 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);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;//从把原始包拷贝到data\app\临时目录下面ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);if (ret != PackageManager.INSTALL_SUCCEEDED) {Slog.e(TAG, "Failed to copy package");return ret;}final File libraryRoot = new File(codeFile, LIB_DIR_NAME);NativeLibraryHelper.Handle handle = null;try {handle = NativeLibraryHelper.Handle.create(codeFile);//拷贝native库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;}
跨进程调用,防止阻塞当前进程
//DefaultContainerService.copyPackage//1@Overridepublic int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {if (packagePath == null || target == null) {return PackageManager.INSTALL_FAILED_INVALID_URI;}PackageLite pkg = null;try {final File packageFile = new File(packagePath);//解析轻量级包//内部调用copyPackageInnerpkg = PackageParser.parsePackageLite(packageFile, 0);return copyPackageInner(pkg, target);} catch (PackageParserException | IOException | RemoteException e) {Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;}}//2private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)throws IOException, RemoteException { //拷贝文件copyFile(pkg.baseCodePath, target, "base.apk");if (!ArrayUtils.isEmpty(pkg.splitNames)) {for (int i = 0; i < pkg.splitNames.length; i++) {copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");}}return PackageManager.INSTALL_SUCCEEDED;}//3private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)throws IOException, RemoteException {Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);InputStream in = null;OutputStream out = null;try {in = new FileInputStream(sourcePath);out = new ParcelFileDescriptor.AutoCloseOutputStream(target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));//拷贝Streams.copy(in, out);} finally {IoUtils.closeQuietly(out);IoUtils.closeQuietly(in);}}
拷贝工作已经完成,接下来就到安装流程了、
//InstallParams.handleReturnCode @Override void handleReturnCode() { // 当mArgs 不为空在走processPendingInstall if (mArgs != null) { processPendingInstall(mArgs, mRet); } }
下面为安装过程入口是PMS.processPendingInstall方法,调用时序图
【下载安装-安装过程图】
//PMS.processPendingInstallprivate 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);}if (!doRestore) {//发送关于安装状态的广播,然后处理安装完的事情,比如打印错误信息,清除临时文件等。Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);mHandler.sendMessage(msg);}}});}//PMS.installPackageTracedLIprivate void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) { try { installPackageLI(args, res); } finally { }}
installPackageLI是安装过程的核心方法,然后调用installPackageLI.首先检查安装包的完整性并解析安装包。
PMS.installPackageLIprivate 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;int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;if (args.move != null) {// moving a complete application; perform an initial scan on the new install locationscanFlags |= 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 returnedres.setReturnCode(PackageManager.INSTALL_SUCCEEDED);res.installerPackageName = installerPackageName;if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);// 合理性检查if (instantApp && (forwardLocked || onExternal)) {Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked+ " external=" + onExternal);res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);return;}// 检索包集和解析包final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY| PackageParser.PARSE_ENFORCE_CODE| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)| (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)| (instantApp ? PackageParser.PARSE_IS_EPHEMERAL : 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 {//解析安装包,主要对Android清单文件的解析pkg = pp.parsePackage(tmpPackageFile, parseFlags);} catch (PackageParserException e) {res.setError("Failed parse during installPackageLI", e);return;} finally {Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}
检查SDK版本和沙箱版本,同时检查是否有静态共享库,如有则需要放在内部存储中。
//[PMS.installPackageLI] //检查SDK版本和沙箱版本if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,"Instant app package must target O");return;}if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {Slog.w(TAG, "Instant app package " + pkg.packageName+ " does not target targetSandboxVersion 2");res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,"Instant app package must use targetSanboxVersion 2");return;}//检查是否有静态共享库if (pkg.applicationInfo.isStaticSharedLibrary()) {// Static shared libraries have synthetic package namesrenameStaticSharedLibraryPackage(pkg);// No static shared libs on external storageif (onExternal) {Slog.i(TAG, "Static shared libs can only be installed on internal storage.");res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,"Packages declaring static-shared libs cannot be updated");return;}}
检查是否有子安装包,如有则子安装包也需要检测。
//[PMS.installPackageLI] // 检查是否有子安装包,如有则子安装包也需要检测。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);}}}
- 检查安装包是否已存在,如已存在则需要检查旧的父包、沙箱、sdk等是否已为空,否则会报错。
- 校验安装包签名
//[PMS.installPackageLI]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);}}if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) {res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "+ pkg.packageName + " upgrade keys do not match the "+ "previously installed version");return;}} else {try {verifySignaturesLP(signatureCheckPs, pkg);} 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);}
如果这是一个系统应用,则检查是否在外部存储上或是是否被其他应用替换等
//[PMS.installPackageLI]if (systemApp) {if (onExternal) {//中止更新;系统app不能被sdcard上的app替换res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,"Cannot install updates to system apps on sdcard");return;} else if (instantApp) {// 中止更新;系统应用程序不能被即时应用程序取代res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,"Cannot update a system app with an instant app");return;}}if (args.move != null) {// 我们做了原地移动,所以dex准备好了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);}//我们按原样移动了整个应用程序,因此引入了以前派生的ABI信息。pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;}} else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) {// 启用SCAN_NO_DEX标志可以在稍后跳过dexoptscanFlags |= SCAN_NO_DEX;try {String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?args.abiOverride : pkg.cpuAbiOverride);final boolean extractNativeLibs = !pkg.isLibrary();derivePackageAbi(pkg, new File(pkg.codePath), abiOverride,extractNativeLibs, mAppLib32InstallDir);} catch (PackageManagerException pme) {Slog.e(TAG, "Error deriving application ABI", pme);res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");return;}// 包的共享库需要更新。synchronized (mPackages) {try {updateSharedLibrariesLPr(pkg, null);} catch (PackageManagerException e) {Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());}}} //把临时路径安装base64加密重命名if (!args.doRename(res.returnCode, pkg, oldCodePath)) {res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");return;}if (!instantApp) {startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);} else {if (DEBUG_DOMAIN_VERIFICATION) {Slog.d(TAG, "Not verifying instant app install for app links: " + pkgName);}}
替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即可。
//[PMS.installPackageLI]//冻结安装包try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,"installPackageLI")) { //替换安装if (replace) {if (pkg.applicationInfo.isStaticSharedLibrary()) {PackageParser.Package existingPkg = mPackages.get(pkg.packageName);if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "+ "static-shared libs cannot be updated");return;}} //replacePackageLIFreplacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,installerPackageName, res, args.installReason);} else { //安装新包installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,args.user, installerPackageName, volumeUuid, res, args.installReason);}}
如有必要,优化dex文件
//[PMS.installPackageLI]final boolean performDexopt = (res.returnCode == PackageManager.INSTALL_SUCCEEDED)&& !forwardLocked&& !pkg.applicationInfo.isExternalAsec()&& (!instantApp || Global.getInt(mContext.getContentResolver(),Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0); //根据条件是否进行dex优化if (performDexopt) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");// Do not run PackageDexOptimizer through the local performDexOpt// method because `pkg` may not be in `mPackages` yet.//// Also, don't fail application installs if the dexopt step fails.DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName,REASON_INSTALL,DexoptOptions.DEXOPT_BOOT_COMPLETE);mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,null /* instructionSets */,getOrCreateCompilerPackageStats(pkg),mDexManager.getPackageUseInfoOrDefault(pkg.packageName),dexoptOptions);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}
先看替换安装的流程,检查安装限制,比如SDK版本,签名的有效性,共享id的检查,普通应用到即时应用的升级,更新删除的内容, 根据需要设置系统/特权标志,更具系统和分系统应用分两步进行。先看系统用。
//PMS.replacePackageLIFprivate void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags,UserHandle user, String installerPackageName, PackageInstalledInfo res,int installReason) {final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;final PackageParser.Package oldPackage;final PackageSetting ps;final String pkgName = pkg.packageName;final int[] allUsers;final int[] installedUsers;synchronized(mPackages) {oldPackage = mPackages.get(pkgName);if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);// 不要允许从预发布SDK升级到正式发布的SDKfinal boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion== android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion== android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;if (oldTargetsPreRelease&& !newTargetsPreRelease&& ((policyFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {Slog.w(TAG, "Can't install package targeting released sdk");res.setReturnCode(PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);return;}ps = mSettings.mPackages.get(pkgName);// 验证签名是否有效if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {if (!checkUpgradeKeySetLP(ps, pkg)) {res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,"New package not signed by keys specified by upgrade-keysets: "+ pkgName);return;}} else {// 默认为原始签名匹配if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)!= PackageManager.SIGNATURE_MATCH) {res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,"New package has a different signature: " + pkgName);return;}}// 除非升级散列匹配,否则不要允许系统升级if (oldPackage.restrictUpdateHash != null && oldPackage.isSystemApp()) {byte[] digestBytes = null;try {final MessageDigest digest = MessageDigest.getInstance("SHA-512");updateDigest(digest, new File(pkg.baseCodePath));if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {for (String path : pkg.splitCodePaths) {updateDigest(digest, new File(path));}}digestBytes = digest.digest();} catch (NoSuchAlgorithmException | IOException e) {res.setError(INSTALL_FAILED_INVALID_APK,"Could not compute hash: " + pkgName);return;}if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) {res.setError(INSTALL_FAILED_INVALID_APK,"New package fails restrict-update check: " + pkgName);return;}// 保留升级限制pkg.restrictUpdateHash = oldPackage.restrictUpdateHash;}// 检查共享用户id更改String invalidPackageName =getParentOrChildPackageChangedSharedUser(oldPackage, pkg);if (invalidPackageName != null) {res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,"Package " + invalidPackageName + " tried to change user "+ oldPackage.mSharedUserId);return;}// 在回滚的情况下,记住每个用户/配置文件的安装状态allUsers = sUserManager.getUserIds();installedUsers = ps.queryInstalledUsers(allUsers, true);// don't allow an upgrade from full to ephemeralif (isInstantApp) {if (user == null || user.getIdentifier() == UserHandle.USER_ALL) {for (int currentUser : allUsers) {if (!ps.getInstantApp(currentUser)) {// can't downgrade from full to instantSlog.w(TAG, "Can't replace full app with instant app: " + pkgName+ " for user: " + currentUser);res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);return;}}} else if (!ps.getInstantApp(user.getIdentifier())) {// can't downgrade from full to instantSlog.w(TAG, "Can't replace full app with instant app: " + pkgName+ " for user: " + user.getIdentifier());res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);return;}}}// 更新删除的内容res.removedInfo = new PackageRemovedInfo(this);res.removedInfo.uid = oldPackage.applicationInfo.uid;res.removedInfo.removedPackage = oldPackage.packageName;res.removedInfo.installerPackageName = ps.installerPackageName;res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;res.removedInfo.isUpdate = true;res.removedInfo.origUsers = installedUsers;res.removedInfo.installReasons = new SparseArray<>(installedUsers.length);for (int i = 0; i < installedUsers.length; i++) {final int userId = installedUsers[i];res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));}final int childCount = (oldPackage.childPackages != null)? oldPackage.childPackages.size() : 0;for (int i = 0; i < childCount; i++) {boolean childPackageUpdated = false;PackageParser.Package childPkg = oldPackage.childPackages.get(i);final PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);if (res.addedChildPackages != null) {PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);if (childRes != null) {childRes.removedInfo.uid = childPkg.applicationInfo.uid;childRes.removedInfo.removedPackage = childPkg.packageName;if (childPs != null) {childRes.removedInfo.installerPackageName = childPs.installerPackageName;}childRes.removedInfo.isUpdate = true;childRes.removedInfo.installReasons = res.removedInfo.installReasons;childPackageUpdated = true;}}if (!childPackageUpdated) {PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);childRemovedRes.removedPackage = childPkg.packageName;if (childPs != null) {childRemovedRes.installerPackageName = childPs.installerPackageName;}childRemovedRes.isUpdate = false;childRemovedRes.dataRemoved = true;synchronized (mPackages) {if (childPs != null) {childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers, true);}}if (res.removedInfo.removedChildPackages == null) {res.removedInfo.removedChildPackages = new ArrayMap<>();}res.removedInfo.removedChildPackages.put(childPkg.packageName, childRemovedRes);}}boolean sysPkg = (isSystemApp(oldPackage));if (sysPkg) {// 根据需要设置系统/特权标志final boolean privileged =(oldPackage.applicationInfo.privateFlags& ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;final int systemPolicyFlags = policyFlags| PackageParser.PARSE_IS_SYSTEM| (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0);replaceSystemPackageLIF(oldPackage, pkg, systemPolicyFlags, scanFlags,user, allUsers, installerPackageName, res, installReason);} else {replaceNonSystemPackageLIF(oldPackage, pkg, policyFlags, scanFlags,user, allUsers, installerPackageName, res, installReason);}}
更新系统包的主要是先删除现有的旧包,禁用替换包,清除原来data目录和配置文件,把原来解析出来的包信息保存到PMS里面
scanPackageTracedLI,点击可以查看这个流程。创建data/data/包名/ 目录,更新相关设置。如果安装失败在回滚旧的安装信息。
//PMS.replaceSystemPackageLIF public void replaceSystemPackageLIF(PackageParser.Package deletedPackage,PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,int[] allUsers, String installerPackageName, PackageInstalledInfo res,int installReason) {final boolean disabledSystem;// 删除现有系统包removePackageLI(deletedPackage, true);synchronized (mPackages) {disabledSystem = disableSystemPackageLPw(deletedPackage, pkg);}if (!disabledSystem) {//我们不需要禁用当前系统包中的.apk,这意味着我们将替换已经安装的另一个更新。我们需要确保删除了老的。res.removedInfo.args = createInstallArgsForExisting(0,deletedPackage.applicationInfo.getCodePath(),deletedPackage.applicationInfo.getResourcePath(),getAppDexInstructionSets(deletedPackage.applicationInfo));} else {res.removedInfo.args = null;}// 成功禁用旧的包。现在继续重新安装//清除原来的data目录clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE| StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);//清除原来应用的配置文件clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL);res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP,ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);PackageParser.Package newPackage = null;try {// 将包添加到内部数据结构中,此处调用请参考初始化安装的流程,这里不做分析。newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, 0, user);//设置更新和安装时间PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras;setInstallAndUpdateTime(newPackage, deletedPkgSetting.firstInstallTime,System.currentTimeMillis());// 如果成功,则更新包的动态状态if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {//既然安装成功了,请确保我们删除了更新删除的子包的数据目录。final int deletedChildCount = (deletedPackage.childPackages != null)? deletedPackage.childPackages.size() : 0;final int newChildCount = (newPackage.childPackages != null)? newPackage.childPackages.size() : 0;for (int i = 0; i < deletedChildCount; i++) {PackageParser.Package deletedChildPkg = deletedPackage.childPackages.get(i);boolean childPackageDeleted = true;for (int j = 0; j < newChildCount; j++) {PackageParser.Package newChildPkg = newPackage.childPackages.get(j);if (deletedChildPkg.packageName.equals(newChildPkg.packageName)) {childPackageDeleted = false;break;}}if (childPackageDeleted) {PackageSetting ps = mSettings.getDisabledSystemPkgLPr(deletedChildPkg.packageName);if (ps != null && res.removedInfo.removedChildPackages != null) {PackageRemovedInfo removedChildRes = res.removedInfo.removedChildPackages.get(deletedChildPkg.packageName);removePackageDataLIF(ps, allUsers, removedChildRes, 0, false);removedChildRes.removedForAllUsers = mPackages.get(ps.name) == null;}}}//更新设置updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,installReason);//准备data目录prepareAppDataAfterInstallLIF(newPackage);//通知dex优化mDexManager.notifyPackageUpdated(newPackage.packageName,newPackage.baseCodePath, newPackage.splitCodePaths);}} catch (PackageManagerException e) {res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);res.setError("Package couldn't be installed in " + pkg.codePath, e);}if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {// 重新安装失败。恢复旧信息,删除新的pkg信息if (newPackage != null) {removeInstalledPackageLI(newPackage, true);}// 添加回旧的系统包 synchronized (mPackages) {if (disabledSystem) {enableSystemPackageLPw(deletedPackage);}// 确保安装包的名称是最新的setInstallerPackageNameLPw(deletedPackage, installerPackageName);// 更新恢复包的权限updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL);//保存包信息到package.xml里面mSettings.writeLPr();}}}
与更新安装系统应用大体相同。
//PMS.replaceNonSystemPackageLIFprivate void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,int[] allUsers, String installerPackageName, PackageInstalledInfo res,int installReason) {String pkgName = deletedPackage.packageName;boolean deletedPkg = true;boolean addedPkg = false;boolean updatedSettings = false;final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;final int deleteFlags = PackageManager.DELETE_KEEP_DATA| (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);final long origUpdateTime = (pkg.mExtras != null)? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;// 首先删除现有的包,同时保留数据目录if (!deletePackageLIF(pkgName, null, true, allUsers, deleteFlags,res.removedInfo, true, pkg)) {//如果现有的包没有被成功删除res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");deletedPkg = false;} else {//成功删除旧包;进行替换。// If deleted package lived in a container, give users a chance to// relinquish resources before killing.if (deletedPackage.isForwardLocked() || isExternal(deletedPackage)) {if (DEBUG_INSTALL) {Slog.i(TAG, "upgrading pkg " + deletedPackage + " is ASEC-hosted -> UNAVAILABLE");}final int[] uidArray = new int[] { deletedPackage.applicationInfo.uid };final ArrayList pkgList = new ArrayList(1);pkgList.add(deletedPackage.applicationInfo.packageName);sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);}clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE| StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL);try {final PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags,scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,installReason);// Update the in-memory copy of the previous code paths.PackageSetting ps = mSettings.mPackages.get(pkgName);if (!killApp) {if (ps.oldCodePaths == null) {ps.oldCodePaths = new ArraySet<>();}Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath);if (deletedPackage.splitCodePaths != null) {Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths);}} else {ps.oldCodePaths = null;}if (ps.childPackageNames != null) {for (int i = ps.childPackageNames.size() - 1; i >= 0; --i) {final String childPkgName = ps.childPackageNames.get(i);final PackageSetting childPs = mSettings.mPackages.get(childPkgName);childPs.oldCodePaths = ps.oldCodePaths;}}// 设置即时应用程序状态,但只有在明确指定的情况下final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0;setInstantAppForUser(ps, user.getIdentifier(), instantApp, fullApp);prepareAppDataAfterInstallLIF(newPackage);addedPkg = true;mDexManager.notifyPackageUpdated(newPackage.packageName,newPackage.baseCodePath, newPackage.splitCodePaths);} catch (PackageManagerException e) {res.setError("Package couldn't be installed in " + pkg.codePath, e);}}if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);// 为失败的安装恢复所有内部状态变化和添加的文件夹if (addedPkg) {deletePackageLIF(pkgName, null, true, allUsers, deleteFlags,res.removedInfo, true, null);}// Restore the old packageif (deletedPkg) {if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);File restoreFile = new File(deletedPackage.codePath);// 恢复旧包boolean oldExternal = isExternal(deletedPackage);int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |(deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0) |(oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;try {scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime,null);} catch (PackageManagerException e) {Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: "+ e.getMessage());return;}synchronized (mPackages) {// 确保安装包的名称是最新的setInstallerPackageNameLPw(deletedPackage, installerPackageName);// 更新恢复包的权限updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL);mSettings.writeLPr();}}} else {//安装成功,更新信息synchronized (mPackages) {PackageSetting ps = mSettings.getPackageLPr(pkg.packageName);if (ps != null) {res.removedInfo.removedForAllUsers = mPackages.get(ps.name) == null;if (res.removedInfo.removedChildPackages != null) {final int childCount = res.removedInfo.removedChildPackages.size();// Iterate in reverse as we may modify the collectionfor (int i = childCount - 1; i >= 0; i--) {String childPackageName = res.removedInfo.removedChildPackages.keyAt(i);if (res.addedChildPackages.containsKey(childPackageName)) {res.removedInfo.removedChildPackages.removeAt(i);} else {PackageRemovedInfo childInfo = res.removedInfo.removedChildPackages.valueAt(i);childInfo.removedForAllUsers = mPackages.get(childInfo.removedPackage) == null;}}}}}}}
接下来看安装一个不存在的新包,流程相对简单。
//PMS.installNewPackageLIF private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,PackageInstalledInfo res, int installReason) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");// 请记住这一点,以防我们需要回滚此安装String pkgName = pkg.packageName;synchronized(mPackages) {final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);if (renamedPackage != null) {// 已经安装了同名的包,尽管它已被重命名为较旧的名称。res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling package running as "+ renamedPackage);return;}if (mPackages.containsKey(pkgName)) {// 不要允许安装在具有相同名称的现有包上。res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling.");return;}}try {//数据转移流程PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,System.currentTimeMillis(), user);//更新设置updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {//准备应用所需的要数据目录prepareAppDataAfterInstallLIF(newPackage);} else {// 从内部结构中删除包,但保留可能已经存在的任何数据deletePackageLIF(pkgName, UserHandle.ALL, false, null,PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);}} catch (PackageManagerException e) {res.setError("Package couldn't be installed in " + pkg.codePath, e);}}
然后为已安装的应用准备数据目录,其依次的顺序是
- PMS.prepareAppDataAfterInstallLIF
- PMS.prepareAppDataLIF
- PMS.prepareAppDataLeafLIF
- Installer.createAppData
以上为下载安装的流程。其中PackageParser .parsePackage(tmpPackageFile, parseFlags)和scanPackageTracedLI这个两个流程在构造函数初始化安装中已经分析,这里不再赘述。请参考Android PackageManagerService(一)启动流程分析
更多相关文章
- Android(安卓)API Demo实例解析
- android sensor framework
- android 运行时生成dex文件,并装载调用
- Android4.4 Camera Gallery 分离
- Android之webView入门
- Firefox OS 学习——manifest.webapp结构分析
- GLSurfaceView 基本使用与源码解析
- Android中GUI系统的Event路由机制
- 简单的音频播放功能MediaPlayer使用中所遇到的坑。