#define LOG_TAG "GraphicsEnv"
#include <gui/GraphicsEnv.h>
+#include <mutex>
+
#include <log/log.h>
+#include <nativeloader/dlext_namespaces.h>
namespace android {
mDriverPath = path;
}
+android_namespace_t* GraphicsEnv::getDriverNamespace() {
+ static std::once_flag once;
+ std::call_once(once, [this]() {
+ // TODO; In the next version of Android, all graphics drivers will be
+ // loaded into a custom namespace. To minimize risk for this release,
+ // only updated drivers use a custom namespace.
+ //
+ // Additionally, the custom namespace will be
+ // ANDROID_NAMESPACE_TYPE_ISOLATED, and will only have access to a
+ // subset of the system.
+ if (mDriverPath.empty())
+ return;
+
+ char defaultPath[PATH_MAX];
+ android_get_LD_LIBRARY_PATH(defaultPath, sizeof(defaultPath));
+ size_t defaultPathLen = strlen(defaultPath);
+
+ std::string path;
+ path.reserve(mDriverPath.size() + 1 + defaultPathLen);
+ path.append(mDriverPath);
+ path.push_back(':');
+ path.append(defaultPath, defaultPathLen);
+
+ mDriverNamespace = android_create_namespace(
+ "gfx driver",
+ nullptr, // ld_library_path
+ path.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_SHARED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
+ });
+ return mDriverNamespace;
+}
+
} // namespace android
#include <string.h>
#include <algorithm>
#include <array>
+#include <dlfcn.h>
#include <new>
#include <malloc.h>
#include <sys/prctl.h>
+#include <android/dlext.h>
+#include <cutils/properties.h>
+#include <gui/GraphicsEnv.h>
+
#include "driver.h"
#include "stubhal.h"
Hal Hal::hal_;
+void* LoadLibrary(const android_dlextinfo& dlextinfo,
+ const char* subname,
+ int subname_len) {
+ const char kLibFormat[] = "vulkan.%*s.so";
+ char* name = static_cast<char*>(
+ alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
+ sprintf(name, kLibFormat, subname_len, subname);
+ return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+}
+
+const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+ "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
+ "ro.board.platform",
+}};
+
+int LoadUpdatedDriver(const hw_module_t** module) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+ };
+ if (!dlextinfo.library_namespace)
+ return -ENOENT;
+
+ void* so = nullptr;
+ char prop[PROPERTY_VALUE_MAX];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ int prop_len = property_get(key, prop, nullptr);
+ if (prop_len > 0) {
+ so = LoadLibrary(dlextinfo, prop, prop_len);
+ if (so)
+ break;
+ }
+ }
+ if (!so)
+ return -ENOENT;
+
+ hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+ if (!hmi) {
+ ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
+ dlclose(so);
+ return -EINVAL;
+ }
+ if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
+ ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
+ dlclose(so);
+ return -EINVAL;
+ }
+ hmi->dso = so;
+ *module = hmi;
+ ALOGD("loaded updated driver");
+ return 0;
+}
+
bool Hal::Open() {
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
// Use a stub device unless we successfully open a real HAL device.
hal_.dev_ = &stubhal::kDevice;
- const hwvulkan_module_t* module;
- int result =
- hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+ int result;
+ const hwvulkan_module_t* module = nullptr;
+
+ result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+ if (result == -ENOENT) {
+ result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+ }
if (result != 0) {
- ALOGI("no Vulkan HAL present, using stub HAL");
+ ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
return true;
}