Merge "Notify the ART runtime when boot is complete."
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index e8f4641..d438103 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -648,6 +648,31 @@
     }
 
     /**
+     * Notify the Zygote processes that boot completed.
+     */
+    public void bootCompleted() {
+        // Notify both the 32-bit and 64-bit zygote.
+        if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+            bootCompleted(Build.SUPPORTED_32_BIT_ABIS[0]);
+        }
+        if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+            bootCompleted(Build.SUPPORTED_64_BIT_ABIS[0]);
+        }
+    }
+
+    private void bootCompleted(String abi) {
+        try {
+            synchronized (mLock) {
+                ZygoteState state = openZygoteSocketIfNeeded(abi);
+                state.mZygoteOutputWriter.write("1\n--boot-completed\n");
+                state.mZygoteOutputWriter.flush();
+            }
+        } catch (Exception ex) {
+            throw new RuntimeException("Failed to inform zygote of boot_completed", ex);
+        }
+    }
+
+    /**
      * Push hidden API blacklisting exemptions into the zygote process(es).
      *
      * <p>The list of exemptions will take affect for all new processes forked from the zygote after
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index af90b15..c64103f 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -169,6 +169,11 @@
     boolean mPidQuery;
 
     /**
+     * Whether the current arguments constitute a notification that boot completed.
+     */
+    boolean mBootCompleted;
+
+    /**
      * Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, or
      * when they change, via --set-api-blacklist-exemptions.
      */
@@ -330,6 +335,8 @@
                 mAbiListQuery = true;
             } else if (arg.equals("--get-pid")) {
                 mPidQuery = true;
+            } else if (arg.equals("--boot-completed")) {
+                mBootCompleted = true;
             } else if (arg.startsWith("--instruction-set=")) {
                 mInstructionSet = arg.substring(arg.indexOf('=') + 1);
             } else if (arg.startsWith("--app-data-dir=")) {
@@ -364,7 +371,11 @@
             }
         }
 
-        if (mAbiListQuery || mPidQuery) {
+        if (mBootCompleted) {
+            if (args.length - curArg > 0) {
+                throw new IllegalArgumentException("Unexpected arguments after --boot-completed");
+            }
+        } else if (mAbiListQuery || mPidQuery) {
             if (args.length - curArg > 0) {
                 throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
             }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index ad9f64c..fc25a47 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -149,6 +149,11 @@
 
         parsedArgs = new ZygoteArguments(args);
 
+        if (parsedArgs.mBootCompleted) {
+            handleBootCompleted();
+            return null;
+        }
+
         if (parsedArgs.mAbiListQuery) {
             handleAbiListQuery();
             return null;
@@ -291,6 +296,10 @@
         }
     }
 
+    private void handleBootCompleted() {
+        VMRuntime.bootCompleted();
+    }
+
     /**
      * 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}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 27ef4a7..78b2914 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7898,6 +7898,10 @@
             }
         }
 
+        // Let the ART runtime in zygote and system_server know that the boot completed.
+        ZYGOTE_PROCESS.bootCompleted();
+        VMRuntime.bootCompleted();
+
         IntentFilter pkgFilter = new IntentFilter();
         pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
         pkgFilter.addDataScheme("package");