Honor the property overrides for GLES.
One of the fundamental problems of the GLES loader is that we never take
ro.hardware.egl and ro.board.platform into account while we try to load the
system driver. As a result, if a device specify the naming via these two
properties, it will not work.
Checking these two properties will allow us to remove a bunch of checks as
well, eventually we want emulator and swiftshader to go through this approach
instead of having a bunch of checks.
Another issue, is that the final loading of the system graphics driver will
load from whatever that match the wildcards of libGLES_*.so or [libEGL_*.so,
libGLESv1_CM_*.so, libGLESv2_*.so]. This is bad, for example, on cuttlefish,
there could be multiple system drivers exist at the same time and cuttlefish
can set ro.hardware.egl during boot time, however, when the graphics driver
fails to load, it will silently load other graphics driver via wildcards
matching. We want to make sure that once the loader fails to load the graphics
driver using system properties, the device can't boot.
In this patch, we attempt to load the system graphics driver by appending these
two properties at the end of the graphics driver library names before we start
to load from the exact names of the graphics driver, and remove the wildcards
matching.
BUG: 127353494
Test: Boots locally, verify emulator.
Test: atest CtsAngleIntegrationHostTestCases
Change-Id: Ib38c797fd3ce5a6e84e2cd38e24c9d3ab3da8274
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 10dd8cb..4b73fe9 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -208,6 +208,11 @@
}
}
+static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
+ "ro.hardware.egl",
+ "ro.board.platform",
+};
+
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
@@ -233,8 +238,30 @@
hnd = attempt_to_load_emulation_driver(cnx);
}
if (!hnd) {
- // Finally, load system driver.
- hnd = attempt_to_load_system_driver(cnx);
+ // Finally, try to load system driver, start by searching for the library name appended by
+ // the system properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop);
+ if (hnd) {
+ break;
+ }
+ }
+ }
+
+ if (!hnd) {
+ // Can't find graphics driver by appending system properties, now search for the exact name
+ // without any suffix of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES.so, or:
+ // libEGL.so, libGLESv1_CM.so, libGLESv2.so
+ hnd = attempt_to_load_system_driver(cnx, nullptr);
}
if (!hnd) {
@@ -408,13 +435,11 @@
return dso;
}
-static void* load_system_driver(const char* kind) {
+static void* load_system_driver(const char* kind, const char* suffix) {
ATRACE_CALL();
class MatchFile {
public:
- static std::string find(const char* kind) {
- std::string result;
- std::string pattern = std::string("lib") + kind;
+ static std::string find(const char* libraryName) {
const char* const searchPaths[] = {
#if defined(__LP64__)
"/vendor/lib64/egl",
@@ -425,74 +450,23 @@
#endif
};
- // first, we search for the exact name of the GLES userspace
- // driver in both locations.
- // i.e.:
- // libGLES.so, or:
- // libEGL.so, libGLESv1_CM.so, libGLESv2.so
-
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], true)) {
- return result;
- }
- }
-
- // for compatibility with the old "egl.cfg" naming convention
- // we look for files that match:
- // libGLES_*.so, or:
- // libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
-
- pattern.append("_");
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], false)) {
- return result;
- }
- }
-
- // we didn't find the driver. gah.
- result.clear();
- return result;
- }
-
- private:
- static bool find(std::string& result,
- const std::string& pattern, const char* const search, bool exact) {
- if (exact) {
- std::string absolutePath = std::string(search) + "/" + pattern + ".so";
+ for (auto dir : searchPaths) {
+ std::string absolutePath = dir + std::string("/") + libraryName + ".so";
if (!access(absolutePath.c_str(), R_OK)) {
- result = absolutePath;
- return true;
+ return absolutePath;
}
- return false;
}
- DIR* d = opendir(search);
- if (d != nullptr) {
- struct dirent* e;
- while ((e = readdir(d)) != nullptr) {
- if (e->d_type == DT_DIR) {
- continue;
- }
- if (!strcmp(e->d_name, "libGLES_android.so")) {
- // always skip the software renderer
- continue;
- }
- if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
- if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
- result = std::string(search) + "/" + e->d_name;
- closedir(d);
- return true;
- }
- }
- }
- closedir(d);
- }
- return false;
+ // Driver not found. gah.
+ return std::string();
}
};
-
- std::string absolutePath = MatchFile::find(kind);
+ std::string libraryName = std::string("lib") + kind;
+ if (suffix) {
+ libraryName += std::string("_") + suffix;
+ }
+ std::string absolutePath = MatchFile::find(libraryName.c_str());
if (absolutePath.empty()) {
// this happens often, we don't want to log an error
return nullptr;
@@ -574,7 +548,20 @@
cnx->angleBackend = angleBackendDefault;
if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
// Find and load vendor libEGL for ANGLE's GL back-end to use.
- cnx->vendorEGL = load_system_driver("EGL");
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ void* dso = load_system_driver("EGL", prop);
+ if (dso) {
+ cnx->vendorEGL = dso;
+ break;
+ }
+ }
+ if (!cnx->vendorEGL) {
+ cnx->vendorEGL = load_system_driver("EGL", nullptr);
+ }
}
} else {
ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
@@ -586,11 +573,6 @@
return so;
}
-static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
- "ro.hardware.egl",
- "ro.board.platform",
-};
-
static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
ATRACE_CALL();
const android_dlextinfo dlextinfo = {
@@ -600,12 +582,13 @@
void* so = nullptr;
char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) > 0) {
- std::string name = std::string("lib") + kind + "_" + prop + ".so";
- so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
- if (so) {
- return so;
- }
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ std::string name = std::string("lib") + kind + "_" + prop + ".so";
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ if (so) {
+ return so;
}
}
return nullptr;
@@ -700,26 +683,26 @@
return hnd;
}
-Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx) {
+Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix) {
ATRACE_CALL();
android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
driver_t* hnd = nullptr;
- void* dso = load_system_driver("GLES");
+ void* dso = load_system_driver("GLES", suffix);
if (dso) {
initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
hnd = new driver_t(dso);
return hnd;
}
- dso = load_system_driver("EGL");
+ dso = load_system_driver("EGL", suffix);
if (dso) {
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_system_driver("GLESv1_CM");
+ dso = load_system_driver("GLESv1_CM", suffix);
initialize_api(dso, cnx, GLESv1_CM);
hnd->set(dso, GLESv1_CM);
- dso = load_system_driver("GLESv2");
+ dso = load_system_driver("GLESv2", suffix);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
}
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index c0f1b75..ebeaeba 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -58,7 +58,7 @@
driver_t* attempt_to_load_angle(egl_connection_t* cnx);
driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
driver_t* attempt_to_load_emulation_driver(egl_connection_t* cnx);
- driver_t* attempt_to_load_system_driver(egl_connection_t* cnx);
+ driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix);
void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))