From b3199f4c04594dae4894358a355fa04aea72c9cf Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 21 Jun 2023 03:01:17 +0000 Subject: [PATCH] Allow per-app opt in to use system ANGLE. Previously the per-app opt in only works for ANGLE apk, this patch refactors the logic to allow per-app opt in to work for system ANGLE. This patch checks whether system ANGLE is supported and if it presents, uses it if the ANGLE apk setup fails. With this patch, the per-app opt in will function this way: 1) When full ANGLE apk is installed Regardless of whether system ANGLE is present, the "angle" option will use ANGLE apk, the "native" option will switch to native GLES drivers specified by ro.hardware.egl, the "default" option will use whatever the default graphics driver is loaded. 2) When full ANGLE apk is not installed and system ANGLE is present The "angle" option will use system ANGLE, the "native" option will switch to native GLES drivers specified by ro.hardware.egl, the "default" option will use whatever the default graphics driver is loaded. 3) When full ANGLE apk is not installed and system ANGLE doesn't exist The per-app option will not function at all. Minor: clean up unused and unnecessary variables. Minor: Avoid sending toast when ANGLE apk doesn't present Bug: b/283858001 Test: test with camera Test: atest CtsAngleIntegrationHostTestCases Change-Id: I83b3c2ccbe7cb38f71418afde4254f48153ab6b3 --- core/java/android/os/GraphicsEnvironment.java | 88 ++++++++++++++----- core/jni/android_os_GraphicsEnvironment.cpp | 17 ++-- 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index c9073fa4b72ca..e6bdfe1b95c4e 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -116,6 +116,8 @@ public class GraphicsEnvironment { private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle"; private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; + private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported"; + private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; @@ -501,10 +503,12 @@ public class GraphicsEnvironment { final List resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); if (resolveInfos.size() != 1) { - Log.e(TAG, "Invalid number of ANGLE packages. Required: 1, Found: " + Log.v(TAG, "Invalid number of ANGLE packages. Required: 1, Found: " + resolveInfos.size()); - for (ResolveInfo resolveInfo : resolveInfos) { - Log.e(TAG, "Found ANGLE package: " + resolveInfo.activityInfo.packageName); + if (DEBUG) { + for (ResolveInfo resolveInfo : resolveInfos) { + Log.d(TAG, "Found ANGLE package: " + resolveInfo.activityInfo.packageName); + } } return ""; } @@ -539,26 +543,42 @@ public class GraphicsEnvironment { } /** - * Determine whether ANGLE should be used, set it up if so, and pass ANGLE details down to - * the C++ GraphicsEnv class. + * Determine whether ANGLE should be used, attempt to set up from apk first, if ANGLE can be + * set up from apk, pass ANGLE details down to the C++ GraphicsEnv class via + * GraphicsEnv::setAngleInfo(). If apk setup fails, attempt to set up to use system ANGLE. + * Return false if both fail. * - * If ANGLE will be used, GraphicsEnv::setAngleInfo() will be called to enable ANGLE to be - * properly used. - * - * @param context - * @param bundle - * @param pm + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageManager - PackageManager of the application process. * @param packageName - package name of the application. - * @return true: ANGLE setup successfully - * false: ANGLE not setup (not on allowlist, ANGLE not present, etc.) + * @return true: can set up to use ANGLE successfully. + * false: can not set up to use ANGLE (not on allowlist, ANGLE not present, etc.) */ - private boolean setupAngle(Context context, Bundle bundle, PackageManager pm, + private boolean setupAngle(Context context, Bundle bundle, PackageManager packageManager, String packageName) { if (!shouldUseAngle(context, bundle, packageName)) { return false; } + return setupAngleFromApk(context, bundle, packageManager, packageName) + || setupAngleFromSystem(context, bundle, packageName); + } + + /** + * Attempt to set up ANGLE from the packaged apk, if the apk can be found, pass ANGLE details to + * the C++ GraphicsEnv class. + * + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageManager - PackageManager of the application process. + * @param packageName - package name of the application. + * @return true: can set up to use ANGLE apk. + * false: can not set up to use ANGLE apk (ANGLE apk not present, etc.) + */ + private boolean setupAngleFromApk(Context context, Bundle bundle, PackageManager packageManager, + String packageName) { ApplicationInfo angleInfo = null; // If the developer has specified a debug package over ADB, attempt to find it @@ -567,7 +587,7 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE debug package enabled: " + anglePkgName); try { // Note the debug package does not have to be pre-installed - angleInfo = pm.getApplicationInfo(anglePkgName, 0); + angleInfo = packageManager.getApplicationInfo(anglePkgName, 0); } catch (PackageManager.NameNotFoundException e) { // If the debug package is specified but not found, abort. Log.v(TAG, "ANGLE debug package '" + anglePkgName + "' not installed"); @@ -577,7 +597,7 @@ public class GraphicsEnvironment { // Otherwise, check to see if ANGLE is properly installed if (angleInfo == null) { - anglePkgName = getAnglePackageName(pm); + anglePkgName = getAnglePackageName(packageManager); if (TextUtils.isEmpty(anglePkgName)) { Log.v(TAG, "Failed to find ANGLE package."); return false; @@ -586,7 +606,7 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE package enabled: " + anglePkgName); try { // Production ANGLE libraries must be pre-installed as a system app - angleInfo = pm.getApplicationInfo(anglePkgName, + angleInfo = packageManager.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { Log.v(TAG, "ANGLE package '" + anglePkgName + "' not installed"); @@ -610,11 +630,35 @@ public class GraphicsEnvironment { // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name, // and features to use. final String[] features = getAngleEglFeatures(context, bundle); - setAngleInfo(paths, packageName, ANGLE_GL_DRIVER_CHOICE_ANGLE, features); + setAngleInfo(paths, false, packageName, features); return true; } + /** + * Attempt to set up ANGLE from system, if the apk can be found, pass ANGLE details to + * the C++ GraphicsEnv class. + * + * @param context - Context of the application. + * @param bundle - Bundle of the application. + * @param packageName - package name of the application. + * @return true: can set up to use system ANGLE. + * false: can not set up to use system ANGLE because it doesn't exist. + */ + private boolean setupAngleFromSystem(Context context, Bundle bundle, String packageName) { + final boolean systemAngleSupported = SystemProperties + .getBoolean(PROPERTY_RO_ANGLE_SUPPORTED, false); + if (!systemAngleSupported) { + return false; + } + + // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name, + // and features to use. + final String[] features = getAngleEglFeatures(context, bundle); + setAngleInfo("", true, packageName, features); + return true; + } + /** * Determine if the "ANGLE In Use" dialog box should be shown. */ @@ -651,7 +695,9 @@ public class GraphicsEnvironment { final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE); final String anglePkg = getAnglePackageName(context.getPackageManager()); - intent.setPackage(anglePkg); + if (anglePkg.isEmpty()) { + return; + } context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { @Override @@ -890,8 +936,8 @@ public class GraphicsEnvironment { private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion); - private static native void setAngleInfo(String path, String packageName, - String devOptIn, String[] features); + private static native void setAngleInfo(String path, boolean useSystemAngle, String packageName, + String[] features); private static native boolean setInjectLayersPrSetDumpable(); private static native void nativeToggleAngleAsSystemDriver(boolean enabled); diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index d94b9828808be..afc3cbd15f88b 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -16,11 +16,12 @@ #define LOG_TAG "GraphicsEnvironment" -#include - #include #include #include + +#include + #include "core_jni_helpers.h" namespace { @@ -49,11 +50,10 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, appPackageNameChars.c_str(), vulkanVersion); } -void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring packageName, - jstring devOptIn, jobjectArray featuresObj) { +void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useSystemAngle, + jstring packageName, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); ScopedUtfChars packageNameChars(env, packageName); - ScopedUtfChars devOptInChars(env, devOptIn); std::vector features; if (featuresObj != nullptr) { @@ -73,8 +73,8 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring packa } } - android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), packageNameChars.c_str(), - devOptInChars.c_str(), features); + android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useSystemAngle, + packageNameChars.c_str(), features); } void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) { @@ -118,8 +118,7 @@ const JNINativeMethod g_methods[] = { reinterpret_cast(setGpuStats_native)}, {"setInjectLayersPrSetDumpable", "()Z", reinterpret_cast(setInjectLayersPrSetDumpable_native)}, - {"setAngleInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", + {"setAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V", reinterpret_cast(setAngleInfo_native)}, {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast(setLayerPaths_native)},