// If this is first boot after an OTA, and a normal boot, then // we need to clear code cache directories. // Note that we do *not* clear the application profiles. These remain valid // across OTAs and are used to drive profile verification (post OTA) and // profile compilation (without waiting to collect a fresh set of profiles). if (mIsUpgrade && !onlyCore) { Slog.i(TAG, "Build fingerprint changed; clearing code caches"); for (inti=0; i < mSettings.mPackages.size(); i++) { finalPackageSettingps= mSettings.mPackages.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) { // No apps are running this early, so no need to freeze clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } } ver.fingerprint = Build.FINGERPRINT; }
privatestatic File preparePackageParserCache(boolean isUpgrade) { if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {//是否开启缓存 returnnull; }
// Disable package parsing on eng builds to allow for faster incremental development. if (Build.IS_ENG) {//ENG版本不使用缓存 returnnull; }
if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) { Slog.i(TAG, "Disabling package parser cache due to system property."); returnnull; }
// The base directory for the package parser cache lives under /data/system/. finalFilecacheBaseDir= FileUtils.createDir(Environment.getDataSystemDirectory(), "package_cache"); if (cacheBaseDir == null) { returnnull; }
// If this is a system upgrade scenario, delete the contents of the package cache dir. // This also serves to "GC" unused entries when the package cache version changes (which // can only happen during upgrades). if (isUpgrade) { FileUtils.deleteContents(cacheBaseDir); }
// Return the versioned package cache directory. This is something like // "/data/system/package_cache/1" FilecacheDir= FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
if (cacheDir == null) { // Something went wrong. Attempt to delete everything and return. Slog.wtf(TAG, "Cache directory cannot be created - wiping base dir " + cacheBaseDir); FileUtils.deleteContentsAndDir(cacheBaseDir); returnnull; }
// The following is a workaround to aid development on non-numbered userdebug // builds or cases where "adb sync" is used on userdebug builds. If we detect that // the system partition is newer. // // NOTE: When no BUILD_NUMBER is set by the build system, it defaults to a build // that starts with "eng." to signify that this is an engineering build and not // destined for release. if (Build.IS_USERDEBUG && Build.VERSION.INCREMENTAL.startsWith("eng.")) { Slog.w(TAG, "Wiping cache directory because the system partition changed.");
// Heuristic: If the /system directory has been modified recently due to an "adb sync" // or a regular make, then blow away the cache. Note that mtimes are *NOT* reliable // in general and should not be used for production changes. In this specific case, // we know that they will work. FileframeworkDir=newFile(Environment.getRootDirectory(), "framework"); if (cacheDir.lastModified() < frameworkDir.lastModified()) { FileUtils.deleteContents(cacheBaseDir); cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION); } }
/** * If {@code useCaches} is true, the package parser might return a cached * result from a previous parse of the same {@code packageFile} with the same * {@code flags}. Note that this method does not check whether {@code packageFile} * has changed since the last parse, it's up to callers to do so. * * @see #parsePackageLite(File, int) */ public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException {//parallelPackageParser传过来的useCaches是true的 Packageparsed= useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; }
/** * Returns the cached parse result for {@code packageFile} for parse flags {@code flags}, * or {@code null} if no cached result exists. */ private Package getCachedResult(File packageFile, int flags) { if (mCacheDir == null) { returnnull; }
try { // If the cache is not up to date, return null. if (!isCacheUpToDate(packageFile, cacheFile)) { returnnull; }
finalbyte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); Packagep= fromCacheEntry(bytes); if (mCallback != null) { String[] overlayApks = mCallback.getOverlayApks(p.packageName); if (overlayApks != null && overlayApks.length > 0) { for (String overlayApk : overlayApks) { // If a static RRO is updated, return null. if (!isCacheUpToDate(newFile(overlayApk), cacheFile)) { returnnull; } } } } return p; } catch (Throwable e) { Slog.w(TAG, "Error reading package cache: ", e);
// If something went wrong while reading the cache entry, delete the cache file // so that we regenerate it the next time. cacheFile.delete(); returnnull; } }