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());
}