初步这样记录一下,晚上会去再总结
/*
* Scan a package and return the newly parsed package.
* Returns null in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
//代表本次扫描系统分区得到的结果
final PackageParser.Package pkg;
try {
//解析传入的文件对象scanFile
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
}
//下面都是使用原始包名的操作 PackageSetting代表<pacakge>
//ps记录扫描
PackageSetting ps = null;
PackageSetting updatedPkg;
// reader
synchronized (mPackages) {
// Look to see if we already know about this package.
//得到当前扫描的pkg的旧包名
String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
// This package has been renamed to its original name. Let‘s
// use that.
//已经被改过名了,得到旧包的那个PackageSetting
ps = mSettings.peekPackageLPr(oldName);
}
// If there was no original package, see one for the real package name.
if (ps == null) {
//并没有被改名,直接用包名得到PackageSetting就是上次扫描的那个
ps = mSettings.peekPackageLPr(pkg.packageName);
}
// Check to see if this package could be hiding/updating a system
// package. Must look for it either under the original or real
// package name depending on our state.
//检查这个旧包名或者新包名的应用是否在升级列表中
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
}
boolean updatedPkgBetter = false;
// First check if this is a system package that may involve an update
if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// If new package is not located in "/system/priv-app" (e.g. due to an OTA),
// it needs to drop FLAG_PRIVILEGED.
if (locationIsPrivileged(scanFile)) {
updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
} else {
updatedPkg.pkgFlags &= ~ApplicationInfo.FLAG_PRIVILEGED;
}
//两者不一致的时候(上次记录的apk目录和本次扫描的apk目录)
if (ps != null && !ps.codePath.equals(scanFile)) {
// The path has changed from what was last scanned... check the
// version of the new path against what we have stored to determine
// what to do.
if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
if (pkg.mVersionCode <= ps.versionCode) {
//说明已经被升级了 (扫描系统的没有上次更新的新) (更多的情况是等于)
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
//升级目录和新扫描目录不一致的时候就直接采用新扫描目录
if (!updatedPkg.codePath.equals(scanFile)) {
Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
+ ps.name + " changing from " + updatedPkg.codePathString
+ " to " + scanFile);
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
}
//更改<updated-package>中记录的apk位置
updatedPkg.pkg = pkg;
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, null);
} else {
//扫描的系统文件比上次扫描的(已经在/data/app/<packageName>下更新的还新)
//pm -r 强制安装一个旧的版本的时候就存在这种情况了,系统的处理也是比较简单的,直接恢复revert成系统的,删除上次
//在data中更新的 (从PMS的扫描列表mPackages中移除就可以了)
// The current app on the system partition is better than
// what we have updated to on the data partition; switch
// back to the system partition version.
// At this point, its safely assumed that package installation for
// apps in system partition will go through. If not there won‘t be a working
// version of the app
// writer
synchronized (mPackages) {
// Just remove the loaded entries from package lists.
mPackages.remove(ps.name);
}
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
synchronized (mPackages) {
//设置为没有升级
mSettings.enableSystemPackageLPw(ps.name);
}
//表示扫描到的当前系统中的更高
updatedPkgBetter = true;
}
}
}
//升级包是存在的,包属性设置为系统属性
if (updatedPkg != null) {
// An updated system app will not have the PARSE_IS_SYSTEM flag set
// initially
parseFlags |= PackageParser.PARSE_IS_SYSTEM;
// An updated privileged app will not have the PARSE_IS_PRIVILEGED
// flag set initially
if ((updatedPkg.pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
// Verify certificates against what was last scanned
collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);
/*
* A new system app appeared, but we already had a non-system one of the
* same name installed earlier.
*/
boolean shouldHideSystemApp = false;
//扫描的是系统应用
if (updatedPkg == null && ps != null
&& (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
/*
* Check to make sure the signatures match first. If they don‘t,
* wipe the installed application and its data.
*/
//扫描到的系统应用和已经存在的普通应用的签名不一样,那么删除扫描到的应用
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
+ " signatures don‘t match existing userdata copy; removing");
deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
ps = null;
} else {
//签名一样的时候
/*
* If the newly-added system app is an older version than the
* already installed version, hide it. It will be scanned later
* and re-added like an update.
*/
//ps 表示已经升级了的
//扫描的系统应用不比上次记录的(也就是已经安装的)高,隐藏掉扫描到的系统应用
if (pkg.mVersionCode <= ps.versionCode) {
shouldHideSystemApp = true;
logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
+ " but new version " + pkg.mVersionCode + " better than installed "
+ ps.versionCode + "; hiding system");
} else {
//扫描到的版本比较高,移除已经安装的,保留数据
/*
* The newly found system app is a newer version that the
* one previously installed. Simply remove the
* already-installed application and replace it with our own
* while keeping the application data.
*/
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString + ": new version "
+ pkg.mVersionCode + " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
}
}
}
//下面处理forward locked app (apk和资源目录不同,则就是forwadlock app)
// The apk is forward locked (not public) if its code and resources
// are kept in different files. (except for app in either system or
// vendor path).
// TODO grab this value from PackageSettings
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
}
// TODO: extend to support forward-locked splits
String resourcePath = null;
String baseResourcePath = null;
//是forward lock app 并且已经升级 (这里用到了上面的updatedPkgBetter变量)
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
// 单独设置资源路径 (其他目录则采用当前的)
if (ps != null && ps.resourcePathString != null) {
resourcePath = ps.resourcePathString;
baseResourcePath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
//当前扫描的系统分区中的版本更高 (经过从上次安装的,重置扫描的)
resourcePath = pkg.codePath;
baseResourcePath = pkg.baseCodePath;
}
// Set application objects path explicitly.
pkg.applicationInfo.setCodePath(pkg.codePath);
pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
pkg.applicationInfo.setResourcePath(resourcePath);
pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
//解析具体目录下的apk
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
/*
* If the system app should be overridden by a previously installed
* data, hide the system app now and let the /data/app scan pick it up
* again.
*/
//本次扫描系统的,没有上次安装的新,隐藏本次扫描的
if (shouldHideSystemApp) {
synchronized (mPackages) {
/*
* We have to grant systems permissions before we hide, because
* grantPermissions will assume the package update is trying to
* expand its permissions.
*/
grantPermissionsLPw(pkg, true, pkg.packageName);
//放在更新列表中
mSettings.disableSystemPackageLPw(pkg.packageName);
}
}
return scannedPkg;
}原文:http://my.oschina.net/wizardmerlin/blog/507472