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

Commit 86cedcb5 authored by Cody Northrop's avatar Cody Northrop
Browse files

Rootless GPU Debug

Add the ability to load GPU debug layers from the base
directory of debuggable applications.

This commit:
* Adds a new Setting to Developer options: "Enable GPU debug layers"
* Adds a new way to discover and specify GPU debug layers per app
* Moves much of the layer enabling logic into GraphicsEnvironment
* Removes the JNI component of ApplicationLoaders

Bug: 63708377
Test: Manual, CTS tests to follow
Change-Id: I7d33e9f835f49aa8d86e63bdb32037728bc8b6a4
parent 3dcb3ec5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5380,7 +5380,7 @@ public final class ActivityThread {
            }
        }

        GraphicsEnvironment.chooseDriver(context);
        GraphicsEnvironment.getInstance().setup(context);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }

+6 −4
Original line number Diff line number Diff line
@@ -17,9 +17,12 @@
package android.app;

import android.os.Build;
import android.os.GraphicsEnvironment;
import android.os.Trace;
import android.util.ArrayMap;

import com.android.internal.os.ClassLoaderFactory;

import dalvik.system.PathClassLoader;

/** @hide */
@@ -72,8 +75,9 @@ public class ApplicationLoaders {

                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupVulkanLayerPath");
                setupVulkanLayerPath(classloader, librarySearchPath);
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setLayerPaths");
                GraphicsEnvironment.getInstance().setLayerPaths(
                        classloader, librarySearchPath, libraryPermittedPath);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

                mLoaders.put(cacheKey, classloader);
@@ -105,8 +109,6 @@ public class ApplicationLoaders {
                              cacheKey, null /* classLoaderName */);
    }

    private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath);

    /**
     * Adds a new path the classpath of the given loader.
     * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
+99 −7
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.pm.PackageManager;
import android.opengl.EGL14;
import android.os.Build;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;

import dalvik.system.VMRuntime;
@@ -29,18 +30,110 @@ import dalvik.system.VMRuntime;
import java.io.File;

/** @hide */
public final class GraphicsEnvironment {
public class GraphicsEnvironment {

    private static final GraphicsEnvironment sInstance = new GraphicsEnvironment();

    /**
     * Returns the shared {@link GraphicsEnvironment} instance.
     */
    public static GraphicsEnvironment getInstance() {
        return sInstance;
    }

    private static final boolean DEBUG = false;
    private static final String TAG = "GraphicsEnvironment";
    private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";

    private ClassLoader mClassLoader;
    private String mLayerPath;
    private String mDebugLayerPath;

    /**
     * Set up GraphicsEnvironment
     */
    public void setup(Context context) {
        setupGpuLayers(context);
        chooseDriver(context);
    }

    /**
     * Check whether application is debuggable
     */
    private static boolean isDebuggable(Context context) {
        return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) > 0;
    }

    /**
     * Store the layer paths available to the loader.
     */
    public void setLayerPaths(ClassLoader classLoader,
                              String layerPath,
                              String debugLayerPath) {
        // We have to store these in the class because they are set up before we
        // have access to the Context to properly set up GraphicsEnvironment
        mClassLoader = classLoader;
        mLayerPath = layerPath;
        mDebugLayerPath = debugLayerPath;
    }

    /**
     * Set up layer search paths for all apps
     * If debuggable, check for additional debug settings
     */
    private void setupGpuLayers(Context context) {

        String layerPaths = "";

        // Only enable additional debug functionality if the following conditions are met:
        // 1. App is debuggable
        // 2. ENABLE_GPU_DEBUG_LAYERS is true
        // 3. Package name is equal to GPU_DEBUG_APP

        if (isDebuggable(context)) {

            int enable = Settings.Global.getInt(context.getContentResolver(),
                                                Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);

            if (enable != 0) {

                String gpuDebugApp = Settings.Global.getString(context.getContentResolver(),
                                                               Settings.Global.GPU_DEBUG_APP);

                String packageName = context.getPackageName();

                if ((gpuDebugApp != null && packageName != null)
                        && (!gpuDebugApp.isEmpty() && !packageName.isEmpty())
                        && gpuDebugApp.equals(packageName)) {
                    Log.i(TAG, "GPU debug layers enabled for " + packageName);

                    // Prepend the debug layer path as a searchable path.
                    // This will ensure debug layers added will take precedence over
                    // the layers specified by the app.
                    layerPaths = mDebugLayerPath + ":";

                    String layers = Settings.Global.getString(context.getContentResolver(),
                                                              Settings.Global.GPU_DEBUG_LAYERS);

                    Log.i(TAG, "Debug layer list: " + layers);
                    if (layers != null && !layers.isEmpty()) {
                        setDebugLayers(layers);
                    }
                }
            }

        }

        // Include the app's lib directory in all cases
        layerPaths += mLayerPath;

        setLayerPaths(mClassLoader, layerPaths);
    }

    /**
     * Choose whether the current process should use the builtin or an updated driver.
     *
     * @hide
     */
    public static void chooseDriver(Context context) {
    private static void chooseDriver(Context context) {
        String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
        if (driverPackageName == null || driverPackageName.isEmpty()) {
            return;
@@ -99,8 +192,6 @@ public final class GraphicsEnvironment {
     * on a separate thread, it can usually be finished well before the UI is ready to be drawn.
     *
     * Should only be called after chooseDriver().
     *
     * @hide
     */
    public static void earlyInitEGL() {
        Thread eglInitThread = new Thread(
@@ -124,6 +215,7 @@ public final class GraphicsEnvironment {
        return null;
    }

    private static native void setLayerPaths(ClassLoader classLoader, String layerPaths);
    private static native void setDebugLayers(String layers);
    private static native void setDriverPath(String path);

}
+21 −0
Original line number Diff line number Diff line
@@ -9843,6 +9843,27 @@ public final class Settings {
         */
        public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";

        /**
         * Allow GPU debug layers?
         * 0 = no
         * 1 = yes
         * @hide
         */
        public static final String ENABLE_GPU_DEBUG_LAYERS = "enable_gpu_debug_layers";

        /**
         * App allowed to load GPU debug layers
         * @hide
         */
        public static final String GPU_DEBUG_APP = "gpu_debug_app";

        /**
         * Ordered GPU debug layer list
         * i.e. <layer1>:<layer2>:...:<layerN>
         * @hide
         */
        public static final String GPU_DEBUG_LAYERS = "gpu_debug_layers";

        /**
         * Control whether the process CPU usage meter should be shown.
         *
+0 −1
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ cc_library_shared {
        "com_google_android_gles_jni_EGLImpl.cpp",
        "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
        "android_app_Activity.cpp",
        "android_app_ApplicationLoaders.cpp",
        "android_app_NativeActivity.cpp",
        "android_app_admin_SecurityLog.cpp",
        "android_opengl_EGL14.cpp",
Loading