Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfdc151d authored by Ryan Savitski's avatar Ryan Savitski
Browse files

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
parent 2e2692d3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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();
}
+8 −1
Original line number Diff line number Diff line
@@ -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 @@ 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) {
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ cc_library_static {
    ],

    include_dirs: [
        "bionic/libc/private",
        "frameworks/base/libs",
        "frameworks/native/services",
        "system/gatekeeper/include",
+9 −0
Original line number Diff line number Diff line
@@ -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 @@ 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)
+10 −0
Original line number Diff line number Diff line
@@ -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();