From afd02885b98d85df0ae516bf8d89b90f9c6f6d00 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Wed, 14 Dec 2016 16:54:06 -0800 Subject: [PATCH] Load updated drivers using derived loader namespace Bug: 33531483 Change-Id: I7e4d5b76d5dde42f2d1b2ad5079a5339a4d11f3d Merged-In: Ia73e1e33b637d6ffd96ea0480ed6d85b9f68dce3 --- include/gui/GraphicsEnv.h | 4 +++ libs/gui/Android.mk | 1 + libs/gui/GraphicsEnv.cpp | 37 ++++++++++++++++++++++++ vulkan/libvulkan/Android.mk | 2 +- vulkan/libvulkan/driver.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/include/gui/GraphicsEnv.h b/include/gui/GraphicsEnv.h index 9f26c14849..0d3843b7c9 100644 --- a/include/gui/GraphicsEnv.h +++ b/include/gui/GraphicsEnv.h @@ -19,6 +19,8 @@ #include +struct android_namespace_t; + namespace android { class GraphicsEnv { @@ -31,10 +33,12 @@ public: // in the search path must have a '!' after the zip filename, e.g. // /data/app/com.example.driver/base.apk!/lib/arm64-v8a void setDriverPath(const std::string path); + android_namespace_t* getDriverNamespace(); private: GraphicsEnv() = default; std::string mDriverPath; + android_namespace_t* mDriverNamespace = nullptr; }; } // namespace android diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 3dbe0e351b..9e2fc2b040 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -76,6 +76,7 @@ LOCAL_SRC_FILES := \ SyncFeatures.cpp \ LOCAL_SHARED_LIBRARIES := \ + libnativeloader \ libbinder \ libcutils \ libEGL \ diff --git a/libs/gui/GraphicsEnv.cpp b/libs/gui/GraphicsEnv.cpp index 99b74bf8fe..ab824d3466 100644 --- a/libs/gui/GraphicsEnv.cpp +++ b/libs/gui/GraphicsEnv.cpp @@ -18,7 +18,10 @@ #define LOG_TAG "GraphicsEnv" #include +#include + #include +#include namespace android { @@ -37,4 +40,38 @@ void GraphicsEnv::setDriverPath(const std::string path) { 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 diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk index d2e28ff665..b7d6791a4e 100644 --- a/vulkan/libvulkan/Android.mk +++ b/vulkan/libvulkan/Android.mk @@ -51,7 +51,7 @@ LOCAL_SRC_FILES := \ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libziparchive -LOCAL_SHARED_LIBRARIES := libhardware libsync libbase liblog libutils libcutils libz +LOCAL_SHARED_LIBRARIES := libgui libhardware libsync libbase liblog libutils libcutils libz LOCAL_MODULE := libvulkan include $(BUILD_SHARED_LIBRARY) diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 25552724d5..741a0ce15c 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -18,10 +18,15 @@ #include #include #include +#include #include #include #include +#include +#include +#include + #include "driver.h" #include "stubhal.h" @@ -123,17 +128,74 @@ class CreateInfoWrapper { 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( + alloca(sizeof(kLibFormat) + static_cast(subname_len))); + sprintf(name, kLibFormat, subname_len, subname); + return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo); +} + +const std::array 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(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(&module)); + int result; + const hwvulkan_module_t* module = nullptr; + + result = LoadUpdatedDriver(reinterpret_cast(&module)); + if (result == -ENOENT) { + result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast(&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; } -- 2.11.0