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

Commit b12249b6 authored by Jesse Hall's avatar Jesse Hall
Browse files

Create GraphicsEnvironment for communicating with driver loaders

The GraphicsEnvironment class is given information during application
start, and makes it available to EGL/GLES/Vulkan loaders that don't
have easy access to the VM or to the application Context. Currently
only the driver path is handled, but the existing support for setting
library paths (for Vulkan extensions) and cache directory information
should move here.

Bug: 33531483
Test: various apps w/ and w/o driver package installed
Change-Id: I5820d3d1301d5461e10706f551b268c54d4f8926
parent c1fdd5df
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import android.os.Bundle;
import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.GraphicsEnvironment;
import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
@@ -5106,7 +5107,7 @@ public final class ActivityThread {
        WindowManagerGlobal.getInstance().trimMemory(level);
    }

    private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
    private void setupGraphicsSupport(Context context, File cacheDir) {
        if (Process.isIsolated()) {
            // Isolated processes aren't going to do UI.
            return;
@@ -5119,6 +5120,7 @@ public final class ActivityThread {
            if (packages != null) {
                ThreadedRenderer.setupDiskCache(cacheDir);
                RenderScriptCacheDir.setupDiskCache(cacheDir);
                GraphicsEnvironment.setupGraphicsEnvironment(context);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
@@ -5422,7 +5424,7 @@ public final class ActivityThread {
            final Context deviceContext = appContext.createDeviceProtectedStorageContext();
            final File codeCacheDir = deviceContext.getCodeCacheDir();
            if (codeCacheDir != null) {
                setupGraphicsSupport(data.info, codeCacheDir);
                setupGraphicsSupport(appContext, codeCacheDir);
            } else {
                Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
            }
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright 2016 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.
 */

package android.os;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.SystemProperties;
import android.util.Log;

import dalvik.system.VMRuntime;

import java.io.File;

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

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

    public static void setupGraphicsEnvironment(Context context) {
        String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
        if (driverPackageName == null || driverPackageName.isEmpty()) {
            return;
        }
        // To minimize risk of driver updates crippling the device beyond user repair, never use an
        // updated driver for privileged or non-updated system apps. Presumably pre-installed apps
        // were tested thoroughly with the pre-installed driver.
        ApplicationInfo ai = context.getApplicationInfo();
        if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
            if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
            return;
        }
        ApplicationInfo driverInfo;
        try {
            driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
                    PackageManager.MATCH_SYSTEM_ONLY);
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
            return;
        }
        String abi = chooseAbi(driverInfo);
        if (abi == null) {
            if (DEBUG) {
                // This is the normal case for the pre-installed empty driver package, don't spam
                if (driverInfo.isUpdatedSystemApp()) {
                    Log.w(TAG, "updated driver package has no compatible native libraries");
                }
            }
            return;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(driverInfo.nativeLibraryDir)
          .append(File.pathSeparator);
        sb.append(driverInfo.sourceDir)
          .append("!/lib/")
          .append(abi);
        String paths = sb.toString();

        if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
        setDriverPath(paths);
    }

    private static String chooseAbi(ApplicationInfo ai) {
        String isa = VMRuntime.getCurrentInstructionSet();
        if (ai.primaryCpuAbi != null &&
                isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) {
            return ai.primaryCpuAbi;
        }
        if (ai.secondaryCpuAbi != null &&
                isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) {
            return ai.secondaryCpuAbi;
        }
        return null;
    }

    private static native void setDriverPath(String path);

}
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ LOCAL_SRC_FILES:= \
    android_text_AndroidBidi.cpp \
    android_text_StaticLayout.cpp \
    android_os_Debug.cpp \
    android_os_GraphicsEnvironment.cpp \
    android_os_HwBinder.cpp \
    android_os_HwBlob.cpp \
    android_os_HwParcel.cpp \
+2 −0
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ extern int register_android_database_SQLiteGlobal(JNIEnv* env);
extern int register_android_database_SQLiteDebug(JNIEnv* env);
extern int register_android_nio_utils(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_GraphicsEnvironment(JNIEnv* env);
extern int register_android_os_HwBinder(JNIEnv *env);
extern int register_android_os_HwBlob(JNIEnv *env);
extern int register_android_os_HwParcel(JNIEnv *env);
@@ -1355,6 +1356,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_database_SQLiteDebug),
    REG_JNI(register_android_os_Debug),
    REG_JNI(register_android_os_FileObserver),
    REG_JNI(register_android_os_GraphicsEnvironment),
    REG_JNI(register_android_os_MessageQueue),
    REG_JNI(register_android_os_SELinux),
    REG_JNI(register_android_os_Trace),
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright 2016 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 "GraphicsEnvironment"

#include <gui/GraphicsEnv.h>
#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"

namespace {

void setDriverPath(JNIEnv* env, jobject clazz, jstring path) {
    ScopedUtfChars pathChars(env, path);
    android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
}

const JNINativeMethod g_methods[] = {
    { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
};

const char* const kGraphicsEnvironmentName = "android/os/GraphicsEnvironment";

} // anonymous namespace

namespace android {

int register_android_os_GraphicsEnvironment(JNIEnv* env) {
    return RegisterMethodsOrDie(env, kGraphicsEnvironmentName, g_methods, NELEM(g_methods));
}

} // namespace android