diff options
-rw-r--r-- | core/java/android/os/ZygoteProcess.java | 20 | ||||
-rw-r--r-- | core/java/com/android/internal/os/WebViewZygoteInit.java | 11 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 45 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 15 |
4 files changed, 80 insertions, 11 deletions
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index fa9f394add60..b3366d883fc6 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -506,4 +506,24 @@ public class ZygoteProcess { state.writer.flush(); } } + + /** + * Instructs the zygote to preload the default set of classes and resources. Returns + * {@code true} if a preload was performed as a result of this call, and {@code false} + * otherwise. The latter usually means that the zygote eagerly preloaded at startup + * or due to a previous call to {@code preloadDefault}. Note that this call is synchronous. + */ + public boolean preloadDefault(String abi) throws ZygoteStartFailedEx, IOException { + synchronized (mLock) { + ZygoteState state = openZygoteSocketIfNeeded(abi); + // Each query starts with the argument count (1 in this case) + state.writer.write("1"); + state.writer.newLine(); + state.writer.write("--preload-default"); + state.writer.newLine(); + state.writer.flush(); + + return (state.inputStream.readInt() == 0); + } + } } diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java index d82a211446d3..f27c0d4df4ce 100644 --- a/core/java/com/android/internal/os/WebViewZygoteInit.java +++ b/core/java/com/android/internal/os/WebViewZygoteInit.java @@ -55,8 +55,15 @@ class WebViewZygoteInit { } @Override - protected void maybePreload() { - // Do nothing, we don't need to call ZygoteInit.maybePreload() for the WebView zygote. + protected void preload() { + // Nothing to preload by default. + } + + @Override + protected boolean isPreloadComplete() { + // Webview zygotes don't preload any classes or resources or defaults, all of their + // preloading is package specific. + return true; } @Override diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index a7f311b33963..e2485e90e537 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -171,7 +171,9 @@ class ZygoteConnection { return handleAbiListQuery(); } - maybePreload(); + if (parsedArgs.preloadDefault) { + return handlePreload(); + } if (parsedArgs.preloadPackage != null) { return handlePreloadPackage(parsedArgs.preloadPackage, @@ -282,8 +284,34 @@ class ZygoteConnection { } } - protected void maybePreload() { - ZygoteInit.maybePreload(); + /** + * Preloads resources if the zygote is in lazily preload mode. Writes the result of the + * preload operation; {@code 0} when a preload was initiated due to this request and {@code 1} + * if no preload was initiated. The latter implies that the zygote is not configured to load + * resources lazy or that the zygote has already handled a previous request to handlePreload. + */ + private boolean handlePreload() { + try { + if (isPreloadComplete()) { + mSocketOutStream.writeInt(1); + } else { + preload(); + mSocketOutStream.writeInt(0); + } + + return false; + } catch (IOException ioe) { + Log.e(TAG, "Error writing to command socket", ioe); + return true; + } + } + + protected void preload() { + ZygoteInit.lazyPreload(); + } + + protected boolean isPreloadComplete() { + return ZygoteInit.isPreloadComplete(); } protected boolean handlePreloadPackage(String packagePath, String libsPath) { @@ -402,6 +430,13 @@ class ZygoteConnection { String preloadPackageLibs; /** + * Whether this is a request to start preloading the default resources and classes. + * This argument only makes sense when the zygote is in lazy preload mode (i.e, when + * it's started with --enable-lazy-preload). + */ + boolean preloadDefault; + + /** * Constructs instance and parses args * @param args zygote command-line args * @throws IllegalArgumentException @@ -564,6 +599,8 @@ class ZygoteConnection { } else if (arg.equals("--preload-package")) { preloadPackage = args[++curArg]; preloadPackageLibs = args[++curArg]; + } else if (arg.equals("--preload-default")) { + preloadDefault = true; } else { break; } @@ -578,7 +615,7 @@ class ZygoteConnection { throw new IllegalArgumentException( "Unexpected arguments after --preload-package."); } - } else { + } else if (!preloadDefault) { if (!seenRuntimeArgs) { throw new IllegalArgumentException("Unexpected argument : " + args[curArg]); } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 1fb31b485325..0b5a1b72f9ea 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -51,6 +51,7 @@ import android.widget.TextView; import com.android.internal.logging.MetricsLogger; +import com.android.internal.util.Preconditions; import dalvik.system.DexFile; import dalvik.system.PathClassLoader; import dalvik.system.VMRuntime; @@ -146,11 +147,11 @@ public class ZygoteInit { sPreloadComplete = true; } - public static void maybePreload() { - if (!sPreloadComplete) { - Log.i(TAG, "Lazily preloading resources."); - preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); - } + public static void lazyPreload() { + Preconditions.checkState(!sPreloadComplete); + Log.i(TAG, "Lazily preloading resources."); + + preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); } private static void beginIcuCachePinning() { @@ -785,6 +786,10 @@ public class ZygoteInit { } } + static boolean isPreloadComplete() { + return sPreloadComplete; + } + /** * Class not instantiable. */ |