From 1cf20cd8498fbb96b6b9878fd3be290d61c16d1c Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Thu, 21 Apr 2022 12:46:41 -0600 Subject: [PATCH 1/2] Can switch to legacy GLES driver when ANGLE is system driver Change the sense of the run-time switches so that ANGLE can be an optional GLES driver or the default system GLES driver. When ANGLE is the system GLES driver, also handle the case of there being no legacy GLES driver. Test: logcat Test: atest CtsAngleIntegrationHostTestCases Test: atest CtsEffectTestCases:android.effect.cts.EffectTest#test5_effectCreate Bug: 224558229 Change-Id: Ie53f5221d51b62db226c0c634537959612a06655 Merged-In: Ie53f5221d51b62db226c0c634537959612a06655 --- core/java/android/os/GraphicsEnvironment.java | 199 +++++++++++++----- core/jni/android_os_GraphicsEnvironment.cpp | 19 +- 2 files changed, 162 insertions(+), 56 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index cb7e6f71a8fd1..20602ce3dca27 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -107,20 +107,42 @@ public class GraphicsEnvironment { private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3; + // System properties related to ANGLE and legacy GLES graphics drivers. + private static final String PROPERTY_EGL_SYSTEM_DRIVER = "ro.hardware.egl"; + // TODO (b/224558229): Properly add this to the list of system properties for a device: + private static final String PROPERTY_EGL_LEGACY_DRIVER = "ro.hardware.egl_legacy"; + // Values for ANGLE_GL_DRIVER_ALL_ANGLE private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1; private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0; + private static final int ANGLE_GL_DRIVER_ALL_LEGACY = -1; // Values for ANGLE_GL_DRIVER_SELECTION_VALUES private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default"; private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle"; + private static final String ANGLE_GL_DRIVER_CHOICE_LEGACY = "legacy"; + // The following value is a deprecated choice for "legacy" private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; + // Values returned by getDriverForPackage() and getDefaultDriverToUse() (avoid returning + // strings for performance reasons) + private static final int ANGLE_GL_DRIVER_TO_USE_LEGACY = 0; + private static final int ANGLE_GL_DRIVER_TO_USE_ANGLE = 1; + private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; private GameManager mGameManager; + private boolean mAngleIsSystemDriver = false; + private boolean mNoLegacyDriver = false; + // When ANGLE is the system driver, this is the name of the legacy driver. + // + // IMPORTANT: When ANGLE is the system driver, and if there is a fallback "legacy" GLES driver + // (e.g. from the GPU provider), the name of that driver must be set here, unles and until + // PROPERTY_EGL_LEGACY_DRIVER has been properly plumbed and this becomes broadly available. + private String mEglLegacyDriver = ""; + private int mAngleOptInIndex = -1; /** @@ -138,6 +160,23 @@ public class GraphicsEnvironment { setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData); Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); + // Determine if ANGLE is the system driver, as this will determine other logic + final String eglSystemDriver = SystemProperties.get(PROPERTY_EGL_SYSTEM_DRIVER); + Log.v(TAG, "GLES system driver is '" + eglSystemDriver + "'"); + mAngleIsSystemDriver = eglSystemDriver.equals(ANGLE_DRIVER_NAME); + if (mAngleIsSystemDriver) { + // Lookup the legacy driver, to send down to the EGL loader + final String eglLegacyDriver = SystemProperties.get(PROPERTY_EGL_LEGACY_DRIVER); + if (eglLegacyDriver.isEmpty()) { + mNoLegacyDriver = true; + mEglLegacyDriver = eglSystemDriver; + } + } else { + mEglLegacyDriver = eglSystemDriver; + } + Log.v(TAG, "Legacy GLES driver is '" + mEglLegacyDriver + "'"); + + // Setup ANGLE and pass down ANGLE details to the C++ code Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle"); boolean useAngle = false; if (setupAngle(context, coreSettings, pm, packageName)) { @@ -145,6 +184,9 @@ public class GraphicsEnvironment { useAngle = true; setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, 0, packageName, getVulkanVersion(pm)); + } else if (mNoLegacyDriver) { + Log.e(TAG, "Unexpected problem with the ANGLE for use with: '" + packageName + "'"); + useAngle = true; } } Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); @@ -188,28 +230,15 @@ public class GraphicsEnvironment { /** * Query to determine if ANGLE should be used */ - private boolean shouldUseAngle(Context context, Bundle coreSettings, - String packageName) { + private boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) { if (TextUtils.isEmpty(packageName)) { - Log.v(TAG, "No package name specified, ANGLE should not be used"); - return false; + Log.v(TAG, "No package name specified; use the system driver"); + return mAngleIsSystemDriver ? true : false; } - final String devOptIn = getDriverForPackage(context, coreSettings, packageName); - Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " - + "set to: '" + devOptIn + "'"); - - // We only want to use ANGLE if the developer has explicitly chosen something other than - // default driver. - final boolean forceAngle = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE); - final boolean forceNative = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE); - if (forceAngle || forceNative) { - Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn); - } - - final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); - - return !forceNative && (forceAngle || gameModeEnabledAngle); + final int driverToUse = getDriverForPackage(context, coreSettings, packageName); + boolean yesOrNo = driverToUse == ANGLE_GL_DRIVER_TO_USE_ANGLE; + return yesOrNo; } private int getVulkanVersion(PackageManager pm) { @@ -417,34 +446,69 @@ public class GraphicsEnvironment { return ai; } - private String getDriverForPackage(Context context, Bundle bundle, String packageName) { + /** + * Return the appropriate "default" driver, unless overridden by isAngleEnabledByGameMode(). + */ + private int getDefaultDriverToUse(Context context, String packageName) { + if (mAngleIsSystemDriver || isAngleEnabledByGameMode(context, packageName)) { + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } else { + return ANGLE_GL_DRIVER_TO_USE_LEGACY; + } + } + + /* + * Determine which GLES "driver" should be used for the package, taking into account the + * following factors (in priority order): + * + * 1) The semi-global switch (i.e. Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE; which is set by + * the "angle_gl_driver_all_angle" setting; which forces a driver for all processes that + * start after the Java run time is up), if it forces a choice; otherwise ... + * 2) The per-application switch (i.e. Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS and + * Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the + * “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it + * forces a choice; otherwise ... + * 3) Use ANGLE if isAngleEnabledByGameMode() returns true; otherwise ... + * 4) The global switch (i.e. use the system driver, whether ANGLE or legacy; + * a.k.a. mAngleIsSystemDriver, which is set by the device’s “ro.hardware.egl” property) + * + * Factors 1 and 2 are decided by this method. Factors 3 and 4 are decided by + * getDefaultDriverToUse(). + */ + private int getDriverForPackage(Context context, Bundle bundle, String packageName) { + // Check the semi-global switch (i.e. once system has booted enough) for whether ANGLE + // should be forced on or off for "all appplications" final int allUseAngle; if (bundle != null) { - allUseAngle = - bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE); + allUseAngle = bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE); } else { ContentResolver contentResolver = context.getContentResolver(); allUseAngle = Settings.Global.getInt(contentResolver, - Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, - ANGLE_GL_DRIVER_ALL_ANGLE_OFF); + Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, ANGLE_GL_DRIVER_ALL_ANGLE_OFF); } if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) { Log.v(TAG, "Turn on ANGLE for all applications."); - return ANGLE_GL_DRIVER_CHOICE_ANGLE; + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } + if (allUseAngle == ANGLE_GL_DRIVER_ALL_LEGACY) { + Log.v(TAG, "Disable ANGLE for all applications."); + return ANGLE_GL_DRIVER_TO_USE_LEGACY; } // Make sure we have a good package name if (TextUtils.isEmpty(packageName)) { - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + return getDefaultDriverToUse(context, packageName); } + // Get the per-application settings lists final ContentResolver contentResolver = context.getContentResolver(); - final List optInPackages = - getGlobalSettingsString(contentResolver, bundle, - Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS); - final List optInValues = - getGlobalSettingsString(contentResolver, bundle, - Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES); + final List optInPackages = getGlobalSettingsString( + contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS); + final List optInValues = getGlobalSettingsString( + contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES); + Log.v(TAG, "Currently set values for:"); + Log.v(TAG, " angle_gl_driver_selection_pkgs = " + optInPackages); + Log.v(TAG, " angle_gl_driver_selection_values =" + optInValues); // Make sure we have good settings to use if (optInPackages.size() != optInValues.size()) { @@ -454,17 +518,40 @@ public class GraphicsEnvironment { + optInPackages.size() + ", " + "number of values: " + optInValues.size()); - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + return getDefaultDriverToUse(context, packageName); } + // See if this application is listed in the per-application settings lists final int pkgIndex = getPackageIndex(packageName, optInPackages); if (pkgIndex < 0) { - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + // The application is NOT listed in the per-application settings lists; and so use the + // system driver (i.e. either ANGLE or the Legacy driver) + Log.v(TAG, "getDriverForPackage(): No per-application setting"); + return getDefaultDriverToUse(context, packageName); } mAngleOptInIndex = pkgIndex; - return optInValues.get(pkgIndex); + Log.v(TAG, + "getDriverForPackage(): using per-application switch: " + + optInValues.get(pkgIndex)); + // The application IS listed in the per-application settings lists; and so use the + // setting--choosing the current system driver if the setting is "default" (i.e. either + // ANGLE or the Legacy driver) + String rtnValue = optInValues.get(pkgIndex); + Log.v(TAG, + "ANGLE Developer option for '" + packageName + "' " + + "set to: '" + rtnValue + "'"); + if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) { + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } else if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE) + || rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_LEGACY)) { + return ANGLE_GL_DRIVER_TO_USE_LEGACY; + } else { + // The user either chose default or an invalid value; go with the default driver or what + // the game dashboard indicates + return getDefaultDriverToUse(context, packageName); + } } /** @@ -514,7 +601,13 @@ public class GraphicsEnvironment { } /** - * Pass ANGLE details down to trigger enable logic + * Determine whether ANGLE should be used, set it up if so, and pass ANGLE details down to + * the C++ GraphicsEnv class. + * + * If ANGLE will be used, GraphicsEnv::setAngleInfo() will be called to enable ANGLE to be + * properly used. Otherwise, GraphicsEnv::setLegacyDriverInfo() will be called to + * enable the legacy GLES driver (e.g. when ANGLE is the system driver) to be identified and + * used. * * @param context * @param bundle @@ -527,6 +620,7 @@ public class GraphicsEnvironment { String packageName) { if (!shouldUseAngle(context, bundle, packageName)) { + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } @@ -541,6 +635,7 @@ public class GraphicsEnvironment { angleInfo = pm.getApplicationInfo(anglePkgName, 0); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "ANGLE debug package '" + anglePkgName + "' not installed"); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } } @@ -550,16 +645,18 @@ public class GraphicsEnvironment { anglePkgName = getAnglePackageName(pm); if (TextUtils.isEmpty(anglePkgName)) { Log.w(TAG, "Failed to find ANGLE package."); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } - Log.i(TAG, "ANGLE package enabled: " + anglePkgName); + Log.v(TAG, "ANGLE package enabled: " + anglePkgName); try { // Production ANGLE libraries must be pre-installed as a system app angleInfo = pm.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed"); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } } @@ -573,21 +670,15 @@ public class GraphicsEnvironment { + "!/lib/" + abi; - if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths); - - // We need to call setAngleInfo() with the package name and the developer option value - //(native/angle/other). Then later when we are actually trying to load a driver, - //GraphicsEnv::getShouldUseAngle() has seen the package name before and can confidently - //answer yes/no based on the previously set developer option value. - final String devOptIn; - final String[] features = getAngleEglFeatures(context, bundle); - final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); - if (gameModeEnabledAngle) { - devOptIn = ANGLE_GL_DRIVER_CHOICE_ANGLE; - } else { - devOptIn = getDriverForPackage(context, bundle, packageName); + if (DEBUG) { + Log.v(TAG, "ANGLE package libs: " + paths); } - setAngleInfo(paths, packageName, devOptIn, features); + + // 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, mAngleIsSystemDriver, ANGLE_GL_DRIVER_CHOICE_ANGLE, features); return true; } @@ -876,8 +967,10 @@ 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 appPackage, String devOptIn, - String[] features); + private static native void setAngleInfo(String path, String appPackage, + boolean angleIsSystemDriver, String devOptIn, String[] features); + private static native void setLegacyDriverInfo( + String appPackage, boolean angleIsSystemDriver, String legacyDriverName); private static native boolean getShouldUseAngle(String packageName); private static native boolean setInjectLayersPrSetDumpable(); diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index f44e829d49d70..78e2d3164993d 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -50,7 +50,7 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, } void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, - jstring devOptIn, jobjectArray featuresObj) { + jboolean angleIsSystemDriver, jstring devOptIn, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); ScopedUtfChars appNameChars(env, appName); ScopedUtfChars devOptInChars(env, devOptIn); @@ -74,7 +74,18 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appNa } android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(), - devOptInChars.c_str(), features); + angleIsSystemDriver, devOptInChars.c_str(), + features); +} + +void setLegacyDriverInfo_native(JNIEnv* env, jobject clazz, jstring appName, + jboolean angleIsSystemDriver, jstring legacyDriverName) { + ScopedUtfChars appNameChars(env, appName); + ScopedUtfChars legacyDriverNameChars(env, legacyDriverName); + + android::GraphicsEnv::getInstance().setLegacyDriverInfo(appNameChars.c_str(), + angleIsSystemDriver, + legacyDriverNameChars.c_str()); } bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) { @@ -120,8 +131,10 @@ const JNINativeMethod g_methods[] = { {"setInjectLayersPrSetDumpable", "()Z", reinterpret_cast(setInjectLayersPrSetDumpable_native)}, {"setAngleInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", + "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V", reinterpret_cast(setAngleInfo_native)}, + {"setLegacyDriverInfo", "(Ljava/lang/String;ZLjava/lang/String;)V", + reinterpret_cast(setLegacyDriverInfo_native)}, {"getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast(shouldUseAngle_native)}, {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", From ce7b086cba5a3d710f0e5c77cb76b5de1091f551 Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Tue, 10 May 2022 16:26:09 -0600 Subject: [PATCH 2/2] Add 2 ANGLE deferlist settings These will be used by the ANGLE Developer Options GUI to process the deferlist Test: logcat + various flash/wipe + system-driver scenarios Bug: 224558229 Change-Id: I47f940612f8be0c83f0be04c2cc1af7908e37382 Merged-In: I47f940612f8be0c83f0be04c2cc1af7908e37382 --- core/java/android/provider/Settings.java | 12 ++++++++++++ core/proto/android/providers/settings/global.proto | 4 ++++ .../providers/settings/SettingsProtoDumpUtil.java | 6 ++++++ .../src/android/provider/SettingsBackupTest.java | 2 ++ 4 files changed, 24 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index df6b827f5cb37..ba7df25c5d7c6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14409,6 +14409,18 @@ public final class Settings { @Readable public static final String ANGLE_EGL_FEATURES = "angle_egl_features"; + /** + * Comma-separated list of package names that ANGLE may have issues with + * @hide + */ + public static final String ANGLE_DEFERLIST = "angle_deferlist"; + + /** + * Integer mode of the logic for applying `angle_deferlist` + * @hide + */ + public static final String ANGLE_DEFERLIST_MODE = "angle_deferlist_mode"; + /** * Show the "ANGLE In Use" dialog box to the user when ANGLE is the OpenGL driver. * The value is a boolean (1 or 0). diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 3c2a48a51b092..e165b079f450b 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -468,6 +468,10 @@ message GlobalSettingsProto { optional SettingProto updatable_driver_prerelease_opt_in_apps = 18; optional SettingProto angle_egl_features = 19; + // ANGLE - List of Apps that ANGLE may have issues with + optional SettingProto angle_deferlist = 20; + // ANGLE - Integer mode of the logic for applying `angle_deferlist` + optional SettingProto angle_deferlist_mode = 21; } optional Gpu gpu = 59; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index ccfeae43e8b6a..8683eac73c6cd 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -770,6 +770,12 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.ANGLE_EGL_FEATURES, GlobalSettingsProto.Gpu.ANGLE_EGL_FEATURES); + dumpSetting(s, p, + Settings.Global.ANGLE_DEFERLIST, + GlobalSettingsProto.Gpu.ANGLE_DEFERLIST); + dumpSetting(s, p, + Settings.Global.ANGLE_DEFERLIST_MODE, + GlobalSettingsProto.Gpu.ANGLE_DEFERLIST_MODE); dumpSetting(s, p, Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, GlobalSettingsProto.Gpu.SHOW_ANGLE_IN_USE_DIALOG); diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index cce515444c1f3..1dc088717e9c5 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -512,6 +512,8 @@ public class SettingsBackupTest { Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, Settings.Global.ANGLE_EGL_FEATURES, + Settings.Global.ANGLE_DEFERLIST, + Settings.Global.ANGLE_DEFERLIST_MODE, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS,