diff options
4 files changed, 67 insertions, 5 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 760df45d2b69..73c9462403f2 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -762,4 +762,19 @@ public class FileUtils { public static @Nullable File newFileOrNull(@Nullable String path) { return (path != null) ? new File(path) : null; } + + /** + * Creates a directory with name {@code name} under an existing directory {@code baseDir}. + * Returns a {@code File} object representing the directory on success, {@code null} on + * failure. + */ + public static @Nullable File createDir(File baseDir, String name) { + final File dir = new File(baseDir, name); + + if (dir.exists()) { + return dir.isDirectory() ? dir : null; + } + + return dir.mkdir() ? dir : null; + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2dd95038e458..1031588317c6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -102,7 +102,6 @@ import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCES import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.IActivityManager; @@ -566,6 +565,18 @@ public class PackageManagerService extends IPackageManager.Stub { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_NUMBER); + + /** + * Version number for the package parser cache. Increment this whenever the format or + * extent of cached data changes. See {@code PackageParser#setCacheDir}. + */ + private static final String PACKAGE_PARSER_CACHE_VERSION = "1"; + + /** + * Whether the package parser cache is enabled. + */ + private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = false; + final ServiceThread mHandlerThread; final PackageHandler mHandler; @@ -804,6 +815,8 @@ public class PackageManagerService extends IPackageManager.Stub { private UserManagerInternal mUserManagerInternal; + private File mCacheDir; + private static class IFVerificationParams { PackageParser.Package pkg; boolean replacing; @@ -2353,6 +2366,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } + mCacheDir = preparePackageParserCache(mIsUpgrade); + // Set flag to monitor and not change apk file paths when // scanning install directories. int scanFlags = SCAN_BOOTING | SCAN_INITIAL; @@ -2815,6 +2830,35 @@ public class PackageManagerService extends IPackageManager.Stub { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } + private static File preparePackageParserCache(boolean isUpgrade) { + if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) { + return null; + } + + if (SystemProperties.getBoolean("ro.boot.disable_package_cache", false)) { + Slog.i(TAG, "Disabling package parser cache due to system property."); + return null; + } + + // The base directory for the package parser cache lives under /data/system/. + final File cacheBaseDir = FileUtils.createDir(Environment.getDataSystemDirectory(), + "package_cache"); + if (cacheBaseDir == null) { + return null; + } + + // 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" + return FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION); + } + @Override public boolean isFirstBoot() { return mFirstBoot; @@ -6938,7 +6982,7 @@ public class PackageManagerService extends IPackageManager.Stub { + " flags=0x" + Integer.toHexString(parseFlags)); } ParallelPackageParser parallelPackageParser = new ParallelPackageParser( - mSeparateProcesses, mOnlyCore, mMetrics); + mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir); // Submit files for parsing in parallel int fileCount = 0; diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java index 73125473df03..603385548689 100644 --- a/services/core/java/com/android/server/pm/ParallelPackageParser.java +++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java @@ -45,6 +45,7 @@ class ParallelPackageParser implements AutoCloseable { private final String[] mSeparateProcesses; private final boolean mOnlyCore; private final DisplayMetrics mMetrics; + private final File mCacheDir; private volatile String mInterruptedInThread; private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY); @@ -53,10 +54,11 @@ class ParallelPackageParser implements AutoCloseable { "package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND); ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps, - DisplayMetrics metrics) { + DisplayMetrics metrics, File cacheDir) { mSeparateProcesses = separateProcesses; mOnlyCore = onlyCoreApps; mMetrics = metrics; + mCacheDir = cacheDir; } static class ParseResult { @@ -107,6 +109,7 @@ class ParallelPackageParser implements AutoCloseable { pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); + pp.setCacheDir(mCacheDir); pr.scanFile = scanFile; pr.pkg = parsePackage(pp, scanFile, parseFlags); } catch (Throwable e) { @@ -129,7 +132,7 @@ class ParallelPackageParser implements AutoCloseable { @VisibleForTesting protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile, int parseFlags) throws PackageParser.PackageParserException { - return packageParser.parsePackage(scanFile, parseFlags); + return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */); } @Override diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java index d165b8b2685c..6c6eb7eebafc 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java @@ -69,7 +69,7 @@ public class ParallelPackageParserTest { class TestParallelPackageParser extends ParallelPackageParser { TestParallelPackageParser() { - super(null, false, null); + super(null, false, null, null); } @Override |