Merge "GL: unload system driver if needed" into qt-dev
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 407f77d..1c5fa52 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -534,60 +534,73 @@
mDebugLayersGLES = layers;
}
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the Game Driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+ const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+ if (llndkLibraries.empty()) {
+ return false;
+ }
+ if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+ ALOGE("Failed to link default namespace[%s]", dlerror());
+ return false;
+ }
+
+ const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+ if (vndkspLibraries.empty()) {
+ return false;
+ }
+ if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+ ALOGE("Failed to link vndk namespace[%s]", dlerror());
+ return false;
+ }
+
+ if (mSphalLibraries.empty()) {
+ return true;
+ }
+
+ // Make additional libraries in sphal to be accessible
+ 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());
+ return false;
+ }
+
+ if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+ ALOGE("Failed to link sphal namespace[%s]", dlerror());
+ return false;
+ }
+
+ return true;
+}
+
android_namespace_t* GraphicsEnv::getDriverNamespace() {
- static std::once_flag once;
- std::call_once(once, [this]() {
- if (mDriverPath.empty()) return;
+ std::lock_guard<std::mutex> lock(mNamespaceMutex);
- auto vndkNamespace = android_get_exported_namespace("vndk");
- if (!vndkNamespace) return;
+ if (mDriverNamespace) {
+ return mDriverNamespace;
+ }
- mDriverNamespace = android_create_namespace("gfx driver",
- mDriverPath.c_str(), // ld_library_path
- mDriverPath.c_str(), // default_library_path
- ANDROID_NAMESPACE_TYPE_ISOLATED,
- nullptr, // permitted_when_isolated_path
- nullptr);
+ if (mDriverPath.empty()) {
+ return nullptr;
+ }
- const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
- if (llndkLibraries.empty()) {
- mDriverNamespace = nullptr;
- return;
- }
- if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
- ALOGE("Failed to link default namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
+ auto vndkNamespace = android_get_exported_namespace("vndk");
+ if (!vndkNamespace) {
+ return nullptr;
+ }
- const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
- if (vndkspLibraries.empty()) {
- mDriverNamespace = nullptr;
- return;
- }
- if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
- ALOGE("Failed to link vndk namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
+ mDriverNamespace = android_create_namespace("gfx driver",
+ mDriverPath.c_str(), // ld_library_path
+ mDriverPath.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr);
- if (mSphalLibraries.empty()) return;
-
- // Make additional libraries in sphal to be accessible
- 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());
- mDriverNamespace = nullptr;
- return;
- }
-
- if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
- ALOGE("Failed to link sphal namespace[%s]", dlerror());
- mDriverNamespace = nullptr;
- return;
- }
- });
+ if (!linkDriverNamespaceLocked(vndkNamespace)) {
+ mDriverNamespace = nullptr;
+ }
return mDriverNamespace;
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 7d62750..f5d19db 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -129,6 +129,7 @@
void* loadLibrary(std::string name);
bool checkAngleRules(void* so);
void updateUseAngle();
+ bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
GraphicsEnv() = default;
std::string mDriverPath;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index d5c46c6..038a432 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -84,6 +84,11 @@
return android_load_sphal_library(path, mode);
}
+static int do_android_unload_sphal_library(void* dso) {
+ ATRACE_CALL();
+ return android_unload_sphal_library(dso);
+}
+
Loader::driver_t::driver_t(void* gles)
{
dso[0] = gles;
@@ -180,11 +185,81 @@
"ro.board.platform",
};
+static bool should_unload_system_driver(egl_connection_t* cnx) {
+ // Return false if the system driver has been unloaded once.
+ if (cnx->systemDriverUnloaded) {
+ return false;
+ }
+
+ // Return true if Angle namespace is set.
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+ if (ns) {
+ return true;
+ }
+
+#ifndef __ANDROID_VNDK__
+ // Return true if updated driver namespace is set.
+ ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (ns) {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
+ while (*api) {
+ *curr++ = nullptr;
+ api++;
+ }
+}
+
+void Loader::unload_system_driver(egl_connection_t* cnx) {
+ ATRACE_CALL();
+
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv2_INDEX]
+ ->gl);
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv1_INDEX]
+ ->gl);
+ uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
+
+ if (cnx->dso) {
+ ALOGD("Unload system gl driver.");
+ driver_t* hnd = (driver_t*)cnx->dso;
+ if (hnd->dso[2]) {
+ do_android_unload_sphal_library(hnd->dso[2]);
+ }
+ if (hnd->dso[1]) {
+ do_android_unload_sphal_library(hnd->dso[1]);
+ }
+ if (hnd->dso[0]) {
+ do_android_unload_sphal_library(hnd->dso[0]);
+ }
+ cnx->dso = nullptr;
+ }
+
+ cnx->systemDriverUnloaded = true;
+}
+
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
const nsecs_t openTime = systemTime();
+ if (should_unload_system_driver(cnx)) {
+ unload_system_driver(cnx);
+ }
+
+ // If a driver has been loaded, return the driver directly.
+ if (cnx->dso) {
+ return cnx->dso;
+ }
+
setEmulatorGlesValue();
// Check if we should use ANGLE early, so loading each driver doesn't require repeated queries.
@@ -244,9 +319,15 @@
"couldn't find an OpenGL ES implementation, make sure you set %s or %s",
HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
- cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
- cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
- cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ if (!cnx->libEgl) {
+ cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+ }
+ if (!cnx->libGles1) {
+ cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ }
+ if (!cnx->libGles2) {
+ cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
+ }
if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
@@ -584,6 +665,7 @@
return nullptr;
}
+ ALOGD("Load updated gl driver.");
android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
driver_t* hnd = nullptr;
void* dso = load_updated_driver("GLES", ns);
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 0292d02..6f31ab4 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -58,6 +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_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
+ void unload_system_driver(egl_connection_t* cnx);
void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 8870d5f..25b1009 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -187,13 +187,9 @@
// dynamically load our EGL implementation
egl_connection_t* cnx = &gEGLImpl;
- if (cnx->dso == nullptr) {
- cnx->hooks[egl_connection_t::GLESv1_INDEX] =
- &gHooks[egl_connection_t::GLESv1_INDEX];
- cnx->hooks[egl_connection_t::GLESv2_INDEX] =
- &gHooks[egl_connection_t::GLESv2_INDEX];
- cnx->dso = loader.open(cnx);
- }
+ cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
+ cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
+ cnx->dso = loader.open(cnx);
// Check to see if any layers are enabled and route functions through them
if (cnx->dso) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 8841a3b..67d69b4 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -217,7 +217,7 @@
Loader& loader(Loader::getInstance());
egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
+ if (cnx->dso) {
EGLDisplay dpy = EGL_NO_DISPLAY;
if (cnx->useAngle) {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 9e112cc..7bb9b59 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -44,7 +44,11 @@
GLESv2_INDEX = 1
};
- inline egl_connection_t() : dso(nullptr) {
+ inline egl_connection_t() : dso(nullptr),
+ libEgl(nullptr),
+ libGles1(nullptr),
+ libGles2(nullptr),
+ systemDriverUnloaded(false) {
char const* const* entries = platform_names;
EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform);
@@ -76,6 +80,7 @@
void* libGles1;
void* libGles2;
+ bool systemDriverUnloaded;
bool shouldUseAngle; // Should we attempt to load ANGLE
bool angleDecided; // Have we tried to load ANGLE
bool useAngle; // Was ANGLE successfully loaded