Allow per-app opt in to use system ANGLE.
Previously the per-app opt in only works for ANGLE apk, this patch
refactors the logic to allow per-app opt in to work for system ANGLE.
This patch checks whether system ANGLE is supported and if it presents,
uses it if the ANGLE apk setup fails.
With this patch, the per-app opt in will function this way:
1) When full ANGLE apk is installed
Regardless of whether system ANGLE is present, the "angle" option will
use ANGLE apk, the "native" option will switch to native GLES drivers
specified by ro.hardware.egl, the "default" option will use whatever the
default graphics driver is loaded.
2) When full ANGLE apk is not installed and system ANGLE is present
The "angle" option will use system ANGLE, the "native" option will
switch to native GLES drivers specified by ro.hardware.egl, the
"default" option will use whatever the default graphics driver is
loaded.
3) When full ANGLE apk is not installed and system ANGLE doesn't exist
The per-app option will not function at all.
To Properly load ANGLE, the namespace of system ANGLE should be
inherited from sphal namespace so that search paths and libraries
linkage are properly constructed.
Minor: clean up unused and unnecessary variables.
Bug: b/283858001
Test: test with camera
Test: atest CtsAngleIntegrationHostTestCases
Change-Id: I2c9d4e1747796d2b0ae58c4456b781b9940fbb26
Merged-In: I2c9d4e1747796d2b0ae58c4456b781b9940fbb26
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;