PMS开机安装更新APK流程

PMS开机启动过程就已经将APK扫描安装到系统,但这个流程策略是怎样的呢?

一、扫描所有系统路径下的APK

主要就是调用scanDirLI方法,这个方法又调用scanPackageLI

      scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            /** M: [ALPS00104673][Need Patch][Volunteer Patch]Mechanism for uninstall app from system partition @{ */
            /// M: [ALPS01210636] Unify path from /vendor to /system/vendor/
            /// So that DVM can find the correct odex
            mOperatorAppInstallDir = new File(Environment.getRootDirectory(), "/vendor/operator/app");

            /// M: [ALPS00270065][Urgent] User mode, cannot move applications to SD
            /// M: [ALPS00338366] Add PARSE_IS_OPERATOR for operator apps
            scanDirLI(mOperatorAppInstallDir, PackageParser.PARSE_IS_OPERATOR, scanFlags, 0);
            /** @} */

            /** M: [CIP] Scan CIP app folder @{ */
            mCustomAppInstallDir = new File("/custom/app");

            /// M: App under CIP folder can be uninstalled
            scanDirLI(mCustomAppInstallDir, PackageParser.PARSE_IS_OPERATOR
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            /** @} */

            /** M: for plugin app @{ */
            /// APP plugin
            mPluginAppInstallDir = new File(Environment.getRootDirectory(), "plugin");

            scanDirLI(mPluginAppInstallDir, PackageParser.PARSE_IS_OPERATOR
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            /// CIP plugin
            mCustomPluginInstallDir = new File("/custom/plugin");

            /// M: App under CIP folder can be uninstalled
            scanDirLI(mCustomPluginInstallDir, PackageParser.PARSE_IS_OPERATOR
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            /** @} */

            // Collect all OEM packages.
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
            mInstaller.moveFiles();

二、找出那些已经被删除和用户在data分区安装过的APK特殊处理

如果这个扫描出的系统APK是disable状态并且在setting列表,说明这个APK进行过自升级,以用户安装的优先

如果这个APK本次没有在系统路径下扫描到,但setting列表里又存在,说明很可能该APK已经被删除了,所以需要清除APK数据

   // Prune any system packages that no longer exist.
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
            if (!mOnlyCore) {
                Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();

                     /*
                      * If this is not a system app, it can't be a
                      * disable system app.
                      */
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        /// M: [Operator] Operator apps are belong to system domain, therefore, need prune.
                        /// M: [Operator] We should also consider OTA from old version without mtkFlag
                        if (!isVendorApp(ps) && !locationIsOperator(ps.codePath)) {
                            continue;
                        }
                    }

                    /*
                     * If the package is scanned, it's not erased.
                     */
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {
                        /*
                         * If the system app is both scanned and in the
                         * disabled packages list, then it must have been
                         * added via OTA. Remove it from the currently
                         * scanned package so the previously user-installed
                         * application can be scanned.
                         */
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                            logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                                    + ps.name + "; removing system app.  Last known codePath="
                                    + ps.codePathString + ", installStatus=" + ps.installStatus
                                    + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                                    + scannedPkg.mVersionCode);
                            removePackageLI(ps, true);
                            mExpectingBetter.put(ps.name, ps.codePath);
                        }

                        continue;
                    }

                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        psit.remove();
                        logCriticalInfo(Log.WARN, "System package " + ps.name
                                + " no longer exists; wiping its data");
                        removeDataDirsLI(null, ps.name);
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                            possiblyDeletedUpdatedSystemApps.add(ps.name);
                        }
                    }
                }
            }

三、处理可能已删除或优先使用data分区的APK

       ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
            //clean up list
            for(int i = 0; i < deletePkgsList.size(); i++) {
                //clean up here
                cleanupInstallFailedPackage(deletePkgsList.get(i));
            }
            //delete tmp files
            deleteTempPackageFiles();

            // Remove any shared userIDs that have no associated packages
            mSettings.pruneSharedUsersLPw();

            if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

                scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
                        scanFlags | SCAN_REQUIRE_KNOWN, 0);

                /**
                 * Remove disable package settings for any updated system
                 * apps that were removed via an OTA. If they're not a
                 * previously-updated app, remove them completely.
                 * Otherwise, just revoke their system-level permissions.
                 */
                for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                    mSettings.removeDisabledSystemPackageLPw(deletedAppName);

                    String msg;
                    if (deletedPkg == null) {
                        msg = "Updated system package " + deletedAppName
                                + " no longer exists; wiping its data";
                        removeDataDirsLI(null, deletedAppName);
                    } else {
                        msg = "Updated system app + " + deletedAppName
                                + " no longer present; removing system privileges for "
                                + deletedAppName;

                        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;

                        /// M: [Operator] Revoke operator permissions for the original operator package
                        /// under operator folder was gone due to OTA
                        deletedPkg.applicationInfo.flagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;

                        PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                        deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;

                        /// M: [Operator] Revoke vendor permissions
                        deletedPs.pkgFlagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;
                    }
                    logCriticalInfo(Log.WARN, msg);
                }

                /**
                 * Make sure all system apps that we expected to appear on
                 * the userdata partition actually showed up. If they never
                 * appeared, crawl back and revive the system version.
                 */
                for (int i = 0; i < mExpectingBetter.size(); i++) {
                    final String packageName = mExpectingBetter.keyAt(i);
                    if (!mPackages.containsKey(packageName)) {
                        final File scanFile = mExpectingBetter.valueAt(i);

                        logCriticalInfo(Log.WARN, "Expected better " + packageName
                                + " but never showed up; reverting to system");

                        final int reparseFlags;
                        if (FileUtils.contains(privilegedAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR
                                    | PackageParser.PARSE_IS_PRIVILEGED;
                        } else if (FileUtils.contains(systemAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else if (FileUtils.contains(oemAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else {
                            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                            continue;
                        }

                        mSettings.enableSystemPackageLPw(packageName);

                        try {
                            scanPackageLI(scanFile, reparseFlags, scanFlags, 0, null);
                        } catch (PackageManagerException e) {
                            Slog.e(TAG, "Failed to parse original system package: "
                                    + e.getMessage());
                        }
                    }
                }
            }
            mExpectingBetter.clear();

系统APK的覆盖安装:

replaceSystemPackageLI函数实现系统APK的覆盖安装,核心是要先清除已安装信息,否则会提示APK已存在

实现已安装系统APK数据清除的代码

  int reparseFlags = PackageParser.PARSE_IS_SYSTEM
				    | PackageParser.PARSE_IS_SYSTEM_DIR;
	    int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
	    File apk_file = new File(originPath);
	    /*****Replace system app start*****/
	    if(replace) {
		    PackageParser pp = new PackageParser();
		    pp.setSeparateProcesses(mSeparateProcesses);
		    pp.setDisplayMetrics(mMetrics);
		    final PackageParser.Package pkg;
		    try {
			pkg = pp.parsePackage(apk_file, reparseFlags);
		    }catch (PackageParserException e) {
			res.setError("Failed parse during installPackageLI", e);
			return;
		    }
		    String packageName = pkg.packageName;
		    PackageParser.Package oldPkg;
		    PackageSetting oldPkgSetting;
		    
		    // reader
		    synchronized (mPackages) {
			oldPkg = mPackages.get(packageName);
			oldPkgSetting = mSettings.mPackages.get(packageName);
			if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
			    (oldPkgSetting == null)) {
			res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE,
				"Couldn't find package:" + packageName + " information");
			return;
			}
		    }
		    
		    killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg");
		    
		    res.removedInfo.uid = oldPkg.applicationInfo.uid;
		    res.removedInfo.removedPackage = packageName;
		    // Remove existing system package
		    removePackageLI(oldPkgSetting, true);
		    // writer
		    /* synchronized (mPackages) {
			disabledSystem = mSettings.disableSystemPackageLPw(packageName);
			if (!disabledSystem && deletedPackage != null) {
			// We didn't need to disable the .apk as a current system package,
			// which means we are replacing another update that is already
			// installed.  We need to make sure to delete the older one's .apk.
			res.removedInfo.args = createInstallArgsForExisting(0,
				deletedPackage.applicationInfo.getCodePath(),
				deletedPackage.applicationInfo.getResourcePath(),
				getAppDexInstructionSets(deletedPackage.applicationInfo));
			} else {
			res.removedInfo.args = null;
			}
		    } */
		    
		    // Successfully disabled the old package. Now proceed with re-installation
		    deleteCodeCacheDirsLI(pkg.volumeUuid, packageName); 
	    }
	    /*****Replace system app end*****/
	    try {
	        //setApplicationEnabledSetting(newPackage.packageName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
	        //0,userId,null);
	        PackageParser.Package newPackage = scanPackageLI(apk_file, reparseFlags, scanFlags, 0L, null);
	        updateSettingsLI(newPackage, installerPackageName, null, null, null, res, new UserHandle(userId));
	        setApplicationEnabledSetting(newPackage.packageName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
	        PackageManager.DONT_KILL_APP,userId,null);
	    } catch (PackageManagerException e) {
	        Log.e(TAG, "lvjiong Failed to parse original system package: "
	    	    + e.getMessage());
	    } 

 

    原文作者:lvjiong353
    原文地址: https://blog.csdn.net/u013463707/article/details/86291896
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞