summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/pm/Installer.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java29
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java40
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtManagerService.java27
5 files changed, 97 insertions, 12 deletions
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f30b3fee7f46..755232c6a6b6 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -628,4 +628,9 @@ public abstract class PackageManagerInternal {
*/
public abstract boolean hasSignatureCapability(int serverUid, int clientUid,
@PackageParser.SigningDetails.CertCapabilities int capability);
+
+ /**
+ * Ask the package manager to compile layouts in the given package.
+ */
+ public abstract boolean compileLayouts(String packageName);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index f0807b9b36d3..a48104a16a9f 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -589,6 +589,14 @@ public class Installer extends SystemService {
throw new InstallerException("Invalid instruction set: " + instructionSet);
}
+ public boolean compileLayouts(String apkPath, String packageName, String outDexFile, int uid) {
+ try {
+ return mInstalld.compileLayouts(apkPath, packageName, outDexFile, uid);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
public static class InstallerException extends Exception {
public InstallerException(String detailMessage) {
super(detailMessage);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f4673a8fa7ba..bf872b7c48f6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -450,6 +450,9 @@ public class PackageManagerService extends IPackageManager.Stub
private static final boolean ENABLE_FREE_CACHE_V2 =
SystemProperties.getBoolean("fw.free_cache_v2", true);
+ private static final boolean PRECOMPILED_LAYOUT_ENABLED =
+ SystemProperties.getBoolean("view.precompiled_layout_enabled", false);
+
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -9177,6 +9180,10 @@ public class PackageManagerService extends IPackageManager.Stub
pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
}
+ if (PRECOMPILED_LAYOUT_ENABLED) {
+ mArtManagerService.compileLayouts(pkg);
+ }
+
// checkProfiles is false to avoid merging profiles during boot which
// might interfere with background compilation (b/28612421).
// Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
@@ -17739,6 +17746,13 @@ public class PackageManagerService extends IPackageManager.Stub
&& ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
if (performDexopt) {
+ // Compile the layout resources.
+ if (PRECOMPILED_LAYOUT_ENABLED) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
+ mArtManagerService.compileLayouts(pkg);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` may not be in `mPackages` yet.
@@ -24483,6 +24497,21 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
PackageManagerService.this.notifyPackageUseLocked(packageName, reason);
}
}
+
+ /**
+ * Ask the package manager to compile layouts in the given package.
+ */
+ @Override
+ public boolean compileLayouts(String packageName) {
+ PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ return false;
+ }
+ }
+ return mArtManagerService.compileLayouts(pkg);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index e5b903024795..e1c13026507f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -41,6 +41,7 @@ import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -1146,6 +1147,7 @@ class PackageManagerShellCommand extends ShellCommand {
String checkProfilesRaw = null;
boolean secondaryDex = false;
String split = null;
+ boolean compileLayouts = false;
String opt;
while ((opt = getNextOption()) != null) {
@@ -1165,6 +1167,9 @@ class PackageManagerShellCommand extends ShellCommand {
case "-r":
compilationReason = getNextArgRequired();
break;
+ case "--compile-layouts":
+ compileLayouts = true;
+ break;
case "--check-prof":
checkProfilesRaw = getNextArgRequired();
break;
@@ -1196,14 +1201,16 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
- if (compilerFilter != null && compilationReason != null) {
- pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
- "at the same time");
- return 1;
- }
- if (compilerFilter == null && compilationReason == null) {
- pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
- "reason (\"-r\") at the same time");
+ final boolean compilerFilterGiven = compilerFilter != null;
+ final boolean compilationReasonGiven = compilationReason != null;
+ // Make sure exactly one of -m, -r, or --compile-layouts is given.
+ if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
+ || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
+ || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
+ || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
+ || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
+ pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
+ "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
return 1;
}
@@ -1217,15 +1224,16 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
- String targetCompilerFilter;
- if (compilerFilter != null) {
+ String targetCompilerFilter = null;
+ if (compilerFilterGiven) {
if (!DexFile.isValidCompilerFilter(compilerFilter)) {
pw.println("Error: \"" + compilerFilter +
"\" is not a valid compilation filter.");
return 1;
}
targetCompilerFilter = compilerFilter;
- } else {
+ }
+ if (compilationReasonGiven) {
int reason = -1;
for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
@@ -1267,12 +1275,19 @@ class PackageManagerShellCommand extends ShellCommand {
pw.flush();
}
- boolean result = secondaryDex
+ boolean result = true;
+ if (compileLayouts) {
+ PackageManagerInternal internal = LocalServices.getService(
+ PackageManagerInternal.class);
+ result = internal.compileLayouts(packageName);
+ } else {
+ result = secondaryDex
? mInterface.performDexOptSecondary(packageName,
targetCompilerFilter, forceCompilation)
: mInterface.performDexOptMode(packageName,
checkProfiles, targetCompilerFilter, forceCompilation,
true /* bootComplete */, split);
+ }
if (!result) {
failedPackages.add(packageName);
}
@@ -2908,6 +2923,7 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
pw.println(" --secondary-dex: compile app secondary dex files");
pw.println(" --split SPLIT: compile only the given split name");
+ pw.println(" --compile-layouts: compile layout resources for faster inflation");
pw.println("");
pw.println(" force-dex-opt PACKAGE");
pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 1f05dc966555..863bfd5ea391 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -472,6 +472,33 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
}
/**
+ * Compile layout resources in a given package.
+ */
+ public boolean compileLayouts(PackageParser.Package pkg) {
+ try {
+ final String packageName = pkg.packageName;
+ final String apkPath = pkg.baseCodePath;
+ final ApplicationInfo appInfo = pkg.applicationInfo;
+ final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex";
+ Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
+ ") to " + outDexFile);
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mInstallLock) {
+ return mInstaller.compileLayouts(apkPath, packageName, outDexFile,
+ appInfo.uid);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+ catch (Throwable e) {
+ Log.e("PackageManager", "Failed to compile layouts", e);
+ return false;
+ }
+ }
+
+ /**
* Build the profiles names for all the package code paths (excluding resource only paths).
* Return the map [code path -> profile name].
*/