ANGLE In Use Dialog Box
When ANGLE is enabled for an app, show a dialog box to the user to
indicate that ANGLE is in use. This is useful because there are
not (or at least shouldn't be) any visual indication that a different
OpenGL driver is in use.
Bug: 120489005
Test: atest CtsAngleIntegrationHostTestCases
Test: Load an app with ANGLE enabled and verify dialog box is shown.
Test: Load an app without ANGLE and verify dialog box is not shown.
Change-Id: I5e87ec96582d43666cfcca2266b46ce98b859a32
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0eadd1d..5f778da 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -65,6 +65,7 @@
import android.os.BadParcelableException;
import android.os.Build;
import android.os.Bundle;
+import android.os.GraphicsEnvironment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -7708,6 +7709,8 @@
}
}
+ GraphicsEnvironment.getInstance().showAngleInUseDialogBox(this);
+
mActivityTransitionState.enterReady(this);
dispatchActivityPostStarted();
}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 269c781..8813e40 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -16,6 +16,7 @@
package android.os;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -30,6 +31,7 @@
import android.provider.Settings;
import android.util.Base64;
import android.util.Log;
+import android.widget.Toast;
import com.android.framework.protobuf.InvalidProtocolBufferException;
@@ -222,9 +224,17 @@
}
- private static List<String> getGlobalSettingsString(Bundle bundle, String globalSetting) {
- List<String> valueList = null;
- final String settingsValue = bundle.getString(globalSetting);
+ private static List<String> getGlobalSettingsString(ContentResolver contentResolver,
+ Bundle bundle,
+ String globalSetting) {
+ final List<String> valueList;
+ final String settingsValue;
+
+ if (bundle != null) {
+ settingsValue = bundle.getString(globalSetting);
+ } else {
+ settingsValue = Settings.Global.getString(contentResolver, globalSetting);
+ }
if (settingsValue != null) {
valueList = new ArrayList<>(Arrays.asList(settingsValue.split(",")));
@@ -246,17 +256,27 @@
return -1;
}
- private static String getDriverForPkg(Bundle bundle, String packageName) {
- final String allUseAngle =
- bundle.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+ private static String getDriverForPkg(Context context, Bundle bundle, String packageName) {
+ final String allUseAngle;
+ if (bundle != null) {
+ allUseAngle =
+ bundle.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+ } else {
+ ContentResolver contentResolver = context.getContentResolver();
+ allUseAngle = Settings.Global.getString(contentResolver,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+ }
if ((allUseAngle != null) && allUseAngle.equals("1")) {
return sDriverMap.get(OpenGlDriverChoice.ANGLE);
}
- final List<String> globalSettingsDriverPkgs = getGlobalSettingsString(
- bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
- final List<String> globalSettingsDriverValues = getGlobalSettingsString(
- bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
+ final ContentResolver contentResolver = context.getContentResolver();
+ final List<String> globalSettingsDriverPkgs =
+ getGlobalSettingsString(contentResolver, bundle,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
+ final List<String> globalSettingsDriverValues =
+ getGlobalSettingsString(contentResolver, bundle,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
// Make sure we have a good package name
if ((packageName == null) || (packageName.isEmpty())) {
@@ -308,7 +328,7 @@
* True: Temporary rules file was loaded.
* False: Temporary rules file was *not* loaded.
*/
- private boolean setupAngleWithTempRulesFile(Context context,
+ private static boolean setupAngleWithTempRulesFile(Context context,
String packageName,
String paths,
String devOptIn) {
@@ -372,7 +392,7 @@
* True: APK rules file was loaded.
* False: APK rules file was *not* loaded.
*/
- private boolean setupAngleRulesApk(String anglePkgName,
+ private static boolean setupAngleRulesApk(String anglePkgName,
ApplicationInfo angleInfo,
PackageManager pm,
String packageName,
@@ -405,23 +425,32 @@
/**
* Pull ANGLE whitelist from GlobalSettings and compare against current package
*/
- private boolean checkAngleWhitelist(Bundle bundle, String packageName) {
+ private static boolean checkAngleWhitelist(Context context, Bundle bundle, String packageName) {
+ final ContentResolver contentResolver = context.getContentResolver();
final List<String> angleWhitelist =
- getGlobalSettingsString(bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST);
+ getGlobalSettingsString(contentResolver, bundle,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST);
return angleWhitelist.contains(packageName);
}
/**
* Pass ANGLE details down to trigger enable logic
+ *
+ * @param context
+ * @param bundle
+ * @param packageName
+ * @return true: ANGLE setup successfully
+ * false: ANGLE not setup (not on whitelist, ANGLE not present, etc.)
*/
- public void setupAngle(Context context, Bundle bundle, PackageManager pm, String packageName) {
+ public boolean setupAngle(Context context, Bundle bundle, PackageManager pm,
+ String packageName) {
if (packageName.isEmpty()) {
Log.v(TAG, "No package name available yet, skipping ANGLE setup");
- return;
+ return false;
}
- final String devOptIn = getDriverForPkg(bundle, packageName);
+ final String devOptIn = getDriverForPkg(context, bundle, packageName);
if (DEBUG) {
Log.v(TAG, "ANGLE Developer option for '" + packageName + "' "
+ "set to: '" + devOptIn + "'");
@@ -439,11 +468,11 @@
// load a driver, GraphicsEnv::shouldUseAngle() has seen the package name before
// and can confidently answer yes/no based on the previously set developer
// option value.
- final boolean whitelisted = checkAngleWhitelist(bundle, packageName);
+ final boolean whitelisted = checkAngleWhitelist(context, bundle, packageName);
final boolean defaulted = devOptIn.equals(sDriverMap.get(OpenGlDriverChoice.DEFAULT));
final boolean rulesCheck = (whitelisted || !defaulted);
if (!rulesCheck) {
- return;
+ return false;
}
if (whitelisted) {
@@ -456,7 +485,7 @@
final String anglePkgName = getAnglePackageName(pm);
if (anglePkgName.isEmpty()) {
Log.e(TAG, "Failed to find ANGLE package.");
- return;
+ return false;
}
final ApplicationInfo angleInfo;
@@ -464,7 +493,7 @@
angleInfo = pm.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed");
- return;
+ return false;
}
final String abi = chooseAbi(angleInfo);
@@ -480,12 +509,62 @@
if (setupAngleWithTempRulesFile(context, packageName, paths, devOptIn)) {
// We setup ANGLE with a temp rules file, so we're done here.
- return;
+ return true;
}
if (setupAngleRulesApk(anglePkgName, angleInfo, pm, packageName, paths, devOptIn)) {
// We setup ANGLE with rules from the APK, so we're done here.
- return;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine if the "ANGLE In Use" dialog box should be shown.
+ */
+ private boolean shouldShowAngleInUseDialogBox(Context context) {
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ final int showDialogBox = Settings.Global.getInt(contentResolver,
+ Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX);
+
+ return (showDialogBox == 1);
+ } catch (Settings.SettingNotFoundException | SecurityException e) {
+ // Do nothing and move on
+ }
+
+ // No setting, so assume false
+ return false;
+ }
+
+ /**
+ * Determine if ANGLE should be used.
+ */
+ private boolean shouldUseAngle(Context context, String packageName) {
+ // Need to make sure we are evaluating ANGLE usage for the correct circumstances
+ if (!setupAngle(context, null, context.getPackageManager(), packageName)) {
+ Log.v(TAG, "Package '" + packageName + "' should use not ANGLE");
+ return false;
+ }
+
+ final boolean useAngle = getShouldUseAngle(packageName);
+ Log.v(TAG, "Package '" + packageName + "' should use ANGLE = '" + useAngle + "'");
+
+ return useAngle;
+ }
+
+ /**
+ * Show the ANGLE in Use Dialog Box
+ * @param context
+ */
+ public void showAngleInUseDialogBox(Context context) {
+ final String packageName = context.getPackageName();
+
+ if (shouldShowAngleInUseDialogBox(context) && shouldUseAngle(context, packageName)) {
+ final String toastMsg = packageName + " is using ANGLE";
+ final Toast toast = Toast.makeText(context, toastMsg, Toast.LENGTH_LONG);
+ toast.show();
}
}
@@ -541,19 +620,19 @@
if (gameDriverAllApps != 1) {
// GAME_DRIVER_OPT_OUT_APPS has higher priority than GAME_DRIVER_OPT_IN_APPS
- if (getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_OUT_APPS)
- .contains(packageName)) {
+ if (getGlobalSettingsString(null, coreSettings,
+ Settings.Global.GAME_DRIVER_OPT_OUT_APPS).contains(packageName)) {
if (DEBUG) {
Log.w(TAG, packageName + " opts out from Game Driver.");
}
return false;
}
final boolean isOptIn =
- getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS)
- .contains(packageName);
+ getGlobalSettingsString(null, coreSettings,
+ Settings.Global.GAME_DRIVER_OPT_IN_APPS).contains(packageName);
if (!isOptIn
- && !getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_WHITELIST)
- .contains(packageName)) {
+ && !getGlobalSettingsString(null, coreSettings,
+ Settings.Global.GAME_DRIVER_WHITELIST).contains(packageName)) {
if (DEBUG) {
Log.w(TAG, packageName + " is not on the whitelist.");
}
@@ -660,4 +739,5 @@
long driverVersionCode, String appPackageName);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
FileDescriptor rulesFd, long rulesOffset, long rulesLength);
+ private static native boolean getShouldUseAngle(String packageName);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c4019ad..2b638f6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12318,6 +12318,14 @@
"angle_whitelist";
/**
+ * Show the "ANGLE In Use" dialog box to the user when ANGLE is the OpenGL driver.
+ * The value is a boolean (1 or 0).
+ * @hide
+ */
+ public static final String GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX =
+ "show_angle_in_use_dialog_box";
+
+ /**
* Game Driver global preference for all Apps.
* 0 = Default
* 1 = All Apps use Game Driver
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index e2e66ce..95f99b7 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -55,6 +55,11 @@
devOptInChars.c_str(), rulesFd_native, rulesOffset, rulesLength);
}
+bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) {
+ ScopedUtfChars appNameChars(env, appName);
+ return android::GraphicsEnv::getInstance().shouldUseAngle(appNameChars.c_str());
+}
+
void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
android::NativeLoaderNamespace* appNamespace = android::FindNativeLoaderNamespaceByClassLoader(
env, classLoader);
@@ -81,6 +86,7 @@
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
{ "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
+ { "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
{ "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
{ "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 39d61a1..c9957f3 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -451,6 +451,8 @@
// Game Driver - List of blacklists, each blacklist is a blacklist for
// a specific Game Driver version
optional SettingProto game_driver_blacklists = 14;
+ // ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG
+ optional SettingProto show_angle_in_use_dialog = 15;
}
optional Gpu gpu = 59;
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index b919553..4d2f005 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -494,6 +494,7 @@
Settings.Global.GAME_DRIVER_BLACKLISTS,
Settings.Global.GAME_DRIVER_BLACKLIST,
Settings.Global.GAME_DRIVER_WHITELIST,
+ Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,