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

Commit 42cf26ec authored by Jesse Hall's avatar Jesse Hall
Browse files

Preload app-process HALs in Zygote

Some HALs, like a.h.graphics.mapper, are always passthrough and are
used by nearly all app processes. Preload those in Zygote to save app
startup time and share more pages between processes. This has the side
effect of also preloading a bunch of HIDL-related system and vndk
libraries that would also otherwise be loaded independently by every
app.

An earlier attempt at this change tried to preload the HAL via a
static initializer in libui.so (which is already preloaded, and which
is the immediate client of the HAL). But several other non-Zygote
processes also use libui.so, and didn't have SELinux permission to
access the device nodes used by the HAL. This version uses an explicit
call from Zygote to preload the HAL, instead of doing it implicitly.

Bug: 62353585
Test: check that a.h.graphics.mapper is in /proc/`pid zygote64`/maps
Change-Id: I42405c3b6cdf1ae412039140d656d15a6d4f8882
(cherry picked from commit 1fe1dc01)
parent 3d0a74a9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -132,6 +132,9 @@ public class ZygoteInit {
        bootTimingsTraceLog.traceBegin("PreloadResources");
        preloadResources();
        bootTimingsTraceLog.traceEnd(); // PreloadResources
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
        nativePreloadAppProcessHALs();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
        preloadOpenGL();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
@@ -184,6 +187,8 @@ public class ZygoteInit {
        System.loadLibrary("jnigraphics");
    }

    native private static void nativePreloadAppProcessHALs();

    private static void preloadOpenGL() {
        String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
        if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
+1 −0
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ cc_library_shared {
        "com_android_internal_os_FuseAppLoop.cpp",
        "com_android_internal_os_PathClassLoaderFactory.cpp",
        "com_android_internal_os_Zygote.cpp",
        "com_android_internal_os_ZygoteInit.cpp",
        "com_android_internal_util_VirtualRefBasePtr.cpp",
        "com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp",
        "hwbinder/EphemeralStorage.cpp",
+4 −2
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);

static AndroidRuntime* gCurRuntime = NULL;
@@ -245,7 +246,7 @@ int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
        methods, NELEM(methods));
}

int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
@@ -1286,7 +1287,7 @@ static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
@@ -1388,6 +1389,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_os_MemoryFile),
    REG_JNI(register_com_android_internal_os_PathClassLoaderFactory),
    REG_JNI(register_com_android_internal_os_Zygote),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
    REG_JNI(register_android_hardware_Camera),
    REG_JNI(register_android_hardware_camera2_CameraMetadata),
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "Zygote"

#include <ui/GraphicBufferMapper.h>

#include "core_jni_helpers.h"

namespace {

void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
    android::GraphicBufferMapper::preloadHal();
    // Add preloading here for other HALs that are (a) always passthrough, and
    // (b) loaded by most app processes.
}

const JNINativeMethod gMethods[] = {
    { "nativePreloadAppProcessHALs", "()V",
      (void*)android_internal_os_ZygoteInit_nativePreloadAppProcessHALs },
};

}  // anonymous namespace

namespace android {

int register_com_android_internal_os_ZygoteInit(JNIEnv* env) {
    return RegisterMethodsOrDie(env, "com/android/internal/os/ZygoteInit",
            gMethods, NELEM(gMethods));
}

}  // namespace android