标签:
初步这样记录一下,晚上会去再总结
/* * 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