From cfdc151d520c3bec26ac2a258648324ab5e542b7 Mon Sep 17 00:00:00 2001 From: Ryan Savitski Date: Fri, 14 Dec 2018 16:20:52 +0000 Subject: [PATCH] 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 --- core/java/android/app/ActivityThread.java | 6 ++++++ core/jni/android_app_ActivityThread.cpp | 9 ++++++++- services/core/jni/Android.bp | 1 + services/core/jni/com_android_server_SystemServer.cpp | 9 +++++++++ services/java/com/android/server/SystemServer.java | 10 ++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7767f0491a166..a3243a5de72a9 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5939,6 +5939,11 @@ public final class ActivityThread extends ClientTransactionHandler { 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 @@ public final class ActivityThread extends ClientTransactionHandler { // ------------------ 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 d56e4c51124dd..93f2525eb29d5 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 +#include + namespace android { static void android_app_ActivityThread_purgePendingResources(JNIEnv* env, jobject clazz) { @@ -38,13 +40,18 @@ android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject java 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 fb00aebb622f0..3729eaf63ddb3 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -53,6 +53,7 @@ cc_library_static { ], 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 dc0d53b41595c..159a4960731d4 100644 --- a/services/core/jni/com_android_server_SystemServer.cpp +++ b/services/core/jni/com_android_server_SystemServer.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -64,6 +66,11 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject / 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 @@ static const JNINativeMethod gMethods[] = { /* 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 cef47caff740b..98385c93aafef 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -326,6 +326,11 @@ public final class SystemServer { */ 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. */ @@ -448,6 +453,11 @@ public final class SystemServer { // 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();