From 79bf392dc6d50436ff16693267c808fc115ab07c Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Mon, 12 Dec 2016 12:53:02 -0800 Subject: [PATCH] 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 Change-Id: I4e4e7fb21f1bcc67122e9173514af5f18c063991 Merged-In: I5820d3d1301d5461e10706f551b268c54d4f8926 --- core/java/android/app/ActivityThread.java | 6 +- core/java/android/os/GraphicsEnvironment.java | 95 +++++++++++++++++++ core/jni/Android.mk | 1 + core/jni/AndroidRuntime.cpp | 2 + core/jni/android_os_GraphicsEnvironment.cpp | 44 +++++++++ 5 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 core/java/android/os/GraphicsEnvironment.java create mode 100644 core/jni/android_os_GraphicsEnvironment.cpp diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 6a2b9aa22928e..5cfcac33050e0 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -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; @@ -5012,7 +5013,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; @@ -5025,6 +5026,7 @@ public final class ActivityThread { if (packages != null) { ThreadedRenderer.setupDiskCache(cacheDir); RenderScriptCacheDir.setupDiskCache(cacheDir); + GraphicsEnvironment.setupGraphicsEnvironment(context); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -5312,7 +5314,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"); } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java new file mode 100644 index 0000000000000..4b130ed1adc8a --- /dev/null +++ b/core/java/android/os/GraphicsEnvironment.java @@ -0,0 +1,95 @@ +/* + * 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); + +} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index dd66b24a6b2f9..6dabc77b0e58e 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -80,6 +80,7 @@ LOCAL_SRC_FILES:= \ android_text_AndroidBidi.cpp \ android_text_StaticLayout.cpp \ android_os_Debug.cpp \ + android_os_GraphicsEnvironment.cpp \ android_os_MemoryFile.cpp \ android_os_MessageQueue.cpp \ android_os_Parcel.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 315887d954e51..174d382c01b3c 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -156,6 +156,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_MessageQueue(JNIEnv* env); extern int register_android_os_Parcel(JNIEnv* env); extern int register_android_os_SELinux(JNIEnv* env); @@ -1348,6 +1349,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), diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp new file mode 100644 index 0000000000000..905a85adc5510 --- /dev/null +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -0,0 +1,44 @@ +/* + * 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 +#include +#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(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