summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/FileUtils.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java48
-rw-r--r--services/core/java/com/android/server/pm/ParallelPackageParser.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java2
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