EGL: Load updated EGL/GLES drivers
Because the driver namespace is stored in libgui, and libgui depends
on libEGL, this required a hack for libEGL to access the namespace.
See the comment added in GraphicsEnv.h for details; the summary is
that the libgui->libEGL dependency should go away, and then libEGL can
depend on libgui directly.
For system drivers, the loader would happily load anything named
lib{GLES,EGL,GLESv2,GLESv1_CM}_*.so in /vendor/lib[64]/egl, for
backward-compatibility with the old and no-longer-supported egl.cfg
system. However, it preferred unsuffixed names. That's not actually a
good idea, since the DT_SONAME would clash with the system libraries.
For updated drivers, we only look for suffixes from the
ro.hardware.egl and ro.board.platform system properties, similar to
the Vulkan and HAL library search. A future change (tied to a future
release) will do the same for system drivers.
Bug: 33531483
Test: Launch GLES apps w/ and w/o updated driver package
Change-Id: Ibfbb275629b0c6cf9c51314aea1361e81ff72d4b
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 218ab35..f5c1422 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -14,6 +14,9 @@
** limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
+#include <array>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -23,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include <android/dlext.h>
#include <cutils/properties.h>
#include <log/log.h>
@@ -154,10 +158,26 @@
// ----------------------------------------------------------------------------
Loader::Loader()
- : getProcAddress(NULL) {
+ : getProcAddress(NULL),
+ mLibGui(nullptr),
+ mGetDriverNamespace(nullptr)
+{
+ // FIXME: See note in GraphicsEnv.h about android_getDriverNamespace().
+ // libgui should already be loaded in any process that uses libEGL, but
+ // if for some reason it isn't, then we're not going to get a driver
+ // namespace anyway, so don't force it to be loaded.
+ mLibGui = dlopen("libgui.so", RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
+ if (!mLibGui) {
+ ALOGD("failed to load libgui: %s", dlerror());
+ return;
+ }
+ mGetDriverNamespace = reinterpret_cast<decltype(mGetDriverNamespace)>(
+ dlsym(mLibGui, "android_getDriverNamespace"));
}
Loader::~Loader() {
+ if (mLibGui)
+ dlclose(mLibGui);
}
static void* load_wrapper(const char* path) {
@@ -304,9 +324,7 @@
}
}
-void *Loader::load_driver(const char* kind,
- egl_connection_t* cnx, uint32_t mask)
-{
+static void* load_system_driver(const char* kind) {
class MatchFile {
public:
static String8 find(const char* kind) {
@@ -431,11 +449,55 @@
ALOGD("loaded %s", driver_absolute_path);
+ return dso;
+}
+
+static const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+ "ro.hardware.egl",
+ "ro.board.platform",
+}};
+
+static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = ns,
+ };
+ void* so = nullptr;
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) > 0) {
+ String8 name;
+ name.appendFormat("lib%s_%s.so", kind, prop);
+ so = android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW,
+ &dlextinfo);
+ if (so)
+ return so;
+ }
+ }
+ return nullptr;
+}
+
+void *Loader::load_driver(const char* kind,
+ egl_connection_t* cnx, uint32_t mask)
+{
+ void* dso = nullptr;
+ if (mGetDriverNamespace) {
+ android_namespace_t* ns = mGetDriverNamespace();
+ if (ns) {
+ dso = load_updated_driver(kind, ns);
+ }
+ }
+ if (!dso) {
+ dso = load_system_driver(kind);
+ if (!dso)
+ return NULL;
+ }
+
if (mask & EGL) {
getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
ALOGE_IF(!getProcAddress,
- "can't find eglGetProcAddress() in %s", driver_absolute_path);
+ "can't find eglGetProcAddress() in EGL driver library");
egl_t* egl = &cnx->egl;
__eglMustCastToProperFunctionPointerType* curr =