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/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/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", 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,