Merge "Allow per-app opt in to use system ANGLE." into main
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 1a638c1..2c274be 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -417,45 +417,28 @@
         return false;
     }
 
-    return (mShouldUseAngle == YES) ? true : false;
+    return mShouldUseAngle;
 }
 
-void GraphicsEnv::updateShouldUseAngle() {
-    const char* ANGLE_PREFER_ANGLE = "angle";
-    const char* ANGLE_PREFER_NATIVE = "native";
-
-    mShouldUseAngle = NO;
-    if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) {
-        ALOGV("User set \"Developer Options\" to force the use of ANGLE");
-        mShouldUseAngle = YES;
-    } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
-        ALOGV("User set \"Developer Options\" to force the use of Native");
-    } else {
-        ALOGV("User set invalid \"Developer Options\": '%s'", mAngleDeveloperOptIn.c_str());
-    }
-}
-
-void GraphicsEnv::setAngleInfo(const std::string& path, const std::string& packageName,
-                               const std::string& developerOptIn,
+void GraphicsEnv::setAngleInfo(const std::string& path, const bool useSystemAngle,
+                               const std::string& packageName,
                                const std::vector<std::string> eglFeatures) {
-    if (mShouldUseAngle != UNKNOWN) {
-        // We've already figured out an answer for this app, so just return.
-        ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", packageName.c_str(),
-              (mShouldUseAngle == YES) ? "true" : "false");
+    if (mShouldUseAngle) {
+        // ANGLE is already set up for this application process, even if the application
+        // needs to switch from apk to system or vice versa, the application process must
+        // be killed and relaunch so that the loader can properly load ANGLE again.
+        // The architecture does not support runtime switch between drivers, so just return.
+        ALOGE("ANGLE is already set for %s", packageName.c_str());
         return;
     }
 
     mAngleEglFeatures = std::move(eglFeatures);
-
     ALOGV("setting ANGLE path to '%s'", path.c_str());
-    mAnglePath = path;
+    mAnglePath = std::move(path);
     ALOGV("setting app package name to '%s'", packageName.c_str());
-    mPackageName = packageName;
-    ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
-    mAngleDeveloperOptIn = developerOptIn;
-
-    // Update the current status of whether we should use ANGLE or not
-    updateShouldUseAngle();
+    mPackageName = std::move(packageName);
+    mShouldUseAngle = true;
+    mUseSystemAngle = useSystemAngle;
 }
 
 void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
@@ -502,13 +485,15 @@
 }
 
 // Return true if all the required libraries from vndk and sphal namespace are
-// linked to the updatable gfx driver namespace correctly.
-bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+// linked to the driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+                                            android_namespace_t* vndkNamespace,
+                                            const std::string& sharedSphalLibraries) {
     const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
     if (llndkLibraries.empty()) {
         return false;
     }
-    if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+    if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
         ALOGE("Failed to link default namespace[%s]", dlerror());
         return false;
     }
@@ -517,12 +502,12 @@
     if (vndkspLibraries.empty()) {
         return false;
     }
-    if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+    if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
         ALOGE("Failed to link vndk namespace[%s]", dlerror());
         return false;
     }
 
-    if (mSphalLibraries.empty()) {
+    if (sharedSphalLibraries.empty()) {
         return true;
     }
 
@@ -530,11 +515,11 @@
     auto sphalNamespace = android_get_exported_namespace("sphal");
     if (!sphalNamespace) {
         ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
-              mSphalLibraries.c_str());
+              sharedSphalLibraries.c_str());
         return false;
     }
 
-    if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+    if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
         ALOGE("Failed to link sphal namespace[%s]", dlerror());
         return false;
     }
@@ -586,7 +571,7 @@
                                                 nullptr, // permitted_when_isolated_path
                                                 nullptr);
 
-    if (!linkDriverNamespaceLocked(vndkNamespace)) {
+    if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
         mDriverNamespace = nullptr;
     }
 
@@ -604,20 +589,48 @@
         return mAngleNamespace;
     }
 
-    if (mAnglePath.empty()) {
-        ALOGV("mAnglePath is empty, not creating ANGLE namespace");
+    if (mAnglePath.empty() && !mUseSystemAngle) {
+        ALOGV("mAnglePath is empty and not using system ANGLE, abort creating ANGLE namespace");
         return nullptr;
     }
 
-    mAngleNamespace = android_create_namespace("ANGLE",
-                                               nullptr,            // ld_library_path
-                                               mAnglePath.c_str(), // default_library_path
-                                               ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
-                                               nullptr, // permitted_when_isolated_path
-                                               nullptr);
+    // Construct the search paths for system ANGLE.
+    const char* const defaultLibraryPaths =
+#if defined(__LP64__)
+            "/vendor/lib64/egl:/system/lib64/egl";
+#else
+            "/vendor/lib/egl:/system/lib/egl";
+#endif
+
+    // If the application process will run on top of system ANGLE, construct the namespace
+    // with sphal namespace being the parent namespace so that search paths and libraries
+    // are properly inherited.
+    mAngleNamespace =
+            android_create_namespace("ANGLE",
+                                     mUseSystemAngle ? defaultLibraryPaths
+                                                     : mAnglePath.c_str(), // ld_library_path
+                                     mUseSystemAngle ? defaultLibraryPaths
+                                                     : mAnglePath.c_str(), // default_library_path
+                                     ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
+                                     nullptr, // permitted_when_isolated_path
+                                     mUseSystemAngle ? android_get_exported_namespace("sphal")
+                                                     : nullptr); // parent
 
     ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
 
+    if (!mUseSystemAngle) {
+        return mAngleNamespace;
+    }
+
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
+
+    if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) {
+        mAngleNamespace = nullptr;
+    }
+
     return mAngleNamespace;
 }
 
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index a1b5e50..e78d038 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -29,6 +29,11 @@
 
 struct NativeLoaderNamespace;
 
+// The GraphicsEnv is a singleton per application process and is used to properly set up the
+// graphics drivers for the application process during application starts. The architecture of
+// the graphics driver loader does not support runtime switch and only supports switch to different
+// graphics drivers when application process launches and hence the only way to switch to different
+// graphics drivers is to completely kill the application process and relaunch the application.
 class GraphicsEnv {
 public:
     static GraphicsEnv& getInstance();
@@ -103,8 +108,8 @@
     // (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& packageName,
-                      const std::string& devOptIn, const std::vector<std::string> eglFeatures);
+    void setAngleInfo(const std::string& path, const bool useSystemAngle,
+                      const std::string& packageName, const std::vector<std::string> eglFeatures);
     // Get the ANGLE driver namespace.
     android_namespace_t* getAngleNamespace();
     // Get the app package name.
@@ -132,12 +137,10 @@
     const std::string& getDebugLayersGLES();
 
 private:
-    enum UseAngle { UNKNOWN, YES, NO };
-
-    // Update whether ANGLE should be used.
-    void updateShouldUseAngle();
     // Link updatable driver namespace with llndk and vndk-sp libs.
-    bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
+    bool linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+                                   android_namespace_t* vndkNamespace,
+                                   const std::string& sharedSphalLibraries);
     // Check whether this process is ready to send stats.
     bool readyToSendGpuStatsLocked();
     // Send the initial complete GpuStats to GpuService.
@@ -165,12 +168,12 @@
     std::string mAnglePath;
     // App's package name.
     std::string mPackageName;
-    // ANGLE developer opt in status.
-    std::string mAngleDeveloperOptIn;
     // ANGLE EGL features;
     std::vector<std::string> mAngleEglFeatures;
-    // Use ANGLE flag.
-    UseAngle mShouldUseAngle = UNKNOWN;
+    // Whether ANGLE should be used.
+    bool mShouldUseAngle = false;
+    // Whether loader should load system ANGLE.
+    bool mUseSystemAngle = false;
     // ANGLE namespace.
     android_namespace_t* mAngleNamespace = nullptr;