zygote children: propagate profileability to bionic for native heap profiling

go/heapprofd is a native heap profiler for android Q+. Its triggering is
implemented within /bionic/libc. App processes (i.e.  zygote children) are not
considered profileable by default on "user" builds. To opt-in into being
profileable, the app's manifest needs to have the Q+ go/profileable flag set
(or be marked as debuggable, which is its superset).

With this change, if the app is supposed to be profileable, post-fork runtime
init calls into bionic to mark itself as such, and possibly start "from
startup" profiling.

On userdebug, all zygote children are marked profileable via the same
mechanism. System server is also marked profileable on userdebug (and needs a
separate codepath, as it does not have an activity thread).

See go/heapprofd-java-trigger for details on why we're taking this approach.
Context on the profiler itself: go/heapprofd-design.

Test: flashed blueline-userdebug, confirmed that java profiling activates from startup and at runtime.
Test: flashed crosshatch-user, confirmed that no java profiling is enabled by default.
Bug: 120409382
Change-Id: Ia038871acfa6b9cae7b6a81f666aecce4b68a4fc
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7767f04..a3243a5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5939,6 +5939,11 @@
             Binder.enableTracing();
         }
 
+        // Initialize heap profiling.
+        if (isAppProfileable || Build.IS_DEBUGGABLE) {
+            nInitZygoteChildHeapProfiling();
+        }
+
         // Allow renderer debugging features if we're debuggable.
         boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
@@ -6965,4 +6970,5 @@
     // ------------------ Regular JNI ------------------------
     private native void nPurgePendingResources();
     private native void nDumpGraphicsInfo(FileDescriptor fd);
+    private native void nInitZygoteChildHeapProfiling();
 }
diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp
index d56e4c5..93f2525 100644
--- a/core/jni/android_app_ActivityThread.cpp
+++ b/core/jni/android_app_ActivityThread.cpp
@@ -24,6 +24,8 @@
 #include "core_jni_helpers.h"
 #include <unistd.h>
 
+#include <bionic_malloc.h>
+
 namespace android {
 
 static void android_app_ActivityThread_purgePendingResources(JNIEnv* env, jobject clazz) {
@@ -38,13 +40,18 @@
     minikin::Layout::dumpMinikinStats(fd);
 }
 
+static void android_app_ActivityThread_initZygoteChildHeapProfiling(JNIEnv* env, jobject clazz) {
+    android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0);
+}
 
 static JNINativeMethod gActivityThreadMethods[] = {
     // ------------ Regular JNI ------------------
     { "nPurgePendingResources",        "()V",
       (void*) android_app_ActivityThread_purgePendingResources },
     { "nDumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
-      (void*) android_app_ActivityThread_dumpGraphics }
+      (void*) android_app_ActivityThread_dumpGraphics },
+    { "nInitZygoteChildHeapProfiling",        "()V",
+      (void*) android_app_ActivityThread_initZygoteChildHeapProfiling }
 };
 
 int register_android_app_ActivityThread(JNIEnv* env) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index fb00aeb..3729eaf 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -53,6 +53,7 @@
     ],
 
     include_dirs: [
+        "bionic/libc/private",
         "frameworks/base/libs",
         "frameworks/native/services",
         "system/gatekeeper/include",
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index dc0d53b..159a496 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -24,6 +24,8 @@
 #include <sensorservice/SensorService.h>
 #include <sensorservicehidl/SensorManager.h>
 
+#include <bionic_malloc.h>
+
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include <utils/misc.h>
@@ -64,6 +66,11 @@
     ALOGE_IF(err != OK, "Cannot register %s: %d", ISchedulingPolicyService::descriptor, err);
 }
 
+static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* env */,
+                                                                     jobject /* clazz */) {
+   android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0);
+}
+
 /*
  * JNI registration.
  */
@@ -71,6 +78,8 @@
     /* name, signature, funcPtr */
     { "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
     { "startHidlServices", "()V", (void*) android_server_SystemServer_startHidlServices },
+    { "initZygoteChildHeapProfiling", "()V",
+      (void*) android_server_SystemServer_initZygoteChildHeapProfiling },
 };
 
 int register_android_server_SystemServer(JNIEnv* env)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cef47ca..98385c9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -327,6 +327,11 @@
     private static native void startHidlServices();
 
     /**
+     * Mark this process' heap as profileable. Only for debug builds.
+     */
+    private static native void initZygoteChildHeapProfiling();
+
+    /**
      * The main entry point from zygote.
      */
     public static void main(String[] args) {
@@ -448,6 +453,11 @@
             // Initialize native services.
             System.loadLibrary("android_servers");
 
+            // Debug builds - allow heap profiling.
+            if (Build.IS_DEBUGGABLE) {
+                initZygoteChildHeapProfiling();
+            }
+
             // Check whether we failed to shut down last time we tried.
             // This call may not return.
             performPendingShutdown();