Update ANGLE Developer Options

Update ANGLE developer options to allow selecting the OpenGL driver
(default, ANGLE, native) for each app as well as forcing ANGLE for all
apps.

Bug: 118384925
Test: Verify the default/ANGLE/native values are saved and applied and
used by the loader.

Change-Id: I389e2b7da171af28efb33b99f437003318ed4ec9
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index c2a6764..dfdda0c 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -135,8 +135,8 @@
 }
 
 void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
-                               bool developerOptIn, const int rulesFd, const long rulesOffset,
-                               const long rulesLength) {
+                               const std::string developerOptIn, const int rulesFd,
+                               const long rulesOffset, const long rulesLength) {
     if (!mAnglePath.empty()) {
         ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
               path.c_str());
@@ -153,7 +153,13 @@
         mAngleAppName = appName;
     }
 
-    mAngleDeveloperOptIn = developerOptIn;
+    if (!mAngleDeveloperOptIn.empty()) {
+        ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'",
+              mAngleDeveloperOptIn.c_str(), developerOptIn.c_str());
+    } else {
+        ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
+        mAngleDeveloperOptIn = developerOptIn;
+    }
 
     ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd);
     mAngleRulesFd = rulesFd;
@@ -182,8 +188,8 @@
     return mAngleAppName.c_str();
 }
 
-bool GraphicsEnv::getAngleDeveloperOptIn() {
-    return mAngleDeveloperOptIn;
+const char* GraphicsEnv::getAngleDeveloperOptIn() {
+    return mAngleDeveloperOptIn.c_str();
 }
 
 int GraphicsEnv::getAngleRulesFd() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 20e4d66..4ec53f1 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -44,12 +44,12 @@
     // (libraries must be stored uncompressed and page aligned); such elements
     // in the search path must have a '!' after the zip filename, e.g.
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
-    void setAngleInfo(const std::string path, const std::string appName, bool devOptIn,
+    void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
                       const int rulesFd, const long rulesOffset, const long rulesLength);
     android_namespace_t* getAngleNamespace();
     const char* getAngleAppName();
     const char* getAngleAppPref();
-    bool getAngleDeveloperOptIn();
+    const char* getAngleDeveloperOptIn();
     int getAngleRulesFd();
     long getAngleRulesOffset();
     long getAngleRulesLength();
@@ -69,7 +69,7 @@
     std::string mDriverPath;
     std::string mAnglePath;
     std::string mAngleAppName;
-    bool mAngleDeveloperOptIn;
+    std::string mAngleDeveloperOptIn;
     int mAngleRulesFd;
     long mAngleRulesOffset;
     long mAngleRulesLength;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 6edadcd..50e30c2 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -41,6 +41,12 @@
 extern "C" {
   android_namespace_t* android_get_exported_namespace(const char*);
 
+  typedef enum ANGLEPreference {
+      ANGLE_PREFER_DEFAULT = 0,
+      ANGLE_PREFER_NATIVE = 1,
+      ANGLE_PREFER_ANGLE = 2,
+  } ANGLEPreference;
+
   // TODO(ianelliott@): Get the following from an ANGLE header:
   // Version-1 API:
   typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse);
@@ -524,6 +530,17 @@
     return nullptr;
 }
 
+static ANGLEPreference getAngleDevOption(const char* devOption) {
+    if (devOption == nullptr)
+        return ANGLE_PREFER_DEFAULT;
+
+    if (strcmp(devOption, "angle") == 0) {
+        return ANGLE_PREFER_ANGLE;
+    } else if (strcmp(devOption, "native") == 0) {
+        return ANGLE_PREFER_NATIVE;
+    }
+    return ANGLE_PREFER_DEFAULT;
+}
 
 static bool check_angle_rules(void* so, const char* app_name) {
     bool use_angle = false;
@@ -646,15 +663,19 @@
     char prop[PROPERTY_VALUE_MAX];
 
     const char* app_name = android::GraphicsEnv::getInstance().getAngleAppName();
-    bool developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
+    const char* developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
 
     // Determine whether or not to use ANGLE:
-    bool use_angle = developer_opt_in;
+    ANGLEPreference developer_option = getAngleDevOption(developer_opt_in);
+    bool use_angle = (developer_option == ANGLE_PREFER_ANGLE);
 
     if (use_angle) {
         ALOGV("User set \"Developer Options\" to force the use of ANGLE");
     } else if (cnx->angleDecided) {
         use_angle = cnx->useAngle;
+    } else if (developer_option == ANGLE_PREFER_NATIVE) {
+        ALOGV("User set \"Developer Options\" to force the use of Native");
+        use_angle = false;
     } else {
         // The "Developer Options" value wasn't set to force the use of ANGLE.  Need to temporarily
         // load ANGLE and call the updatable opt-in/out logic: