OSDN Git Service

Load updated drivers using derived loader namespace
authorJesse Hall <jessehall@google.com>
Thu, 15 Dec 2016 00:54:06 +0000 (16:54 -0800)
committerJesse Hall <jessehall@google.com>
Tue, 17 Jan 2017 17:33:32 +0000 (09:33 -0800)
Bug: 33531483
Change-Id: I7e4d5b76d5dde42f2d1b2ad5079a5339a4d11f3d
Merged-In: Ia73e1e33b637d6ffd96ea0480ed6d85b9f68dce3

include/gui/GraphicsEnv.h
libs/gui/Android.mk
libs/gui/GraphicsEnv.cpp
vulkan/libvulkan/Android.mk
vulkan/libvulkan/driver.cpp

index 9f26c14..0d3843b 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <string>
 
+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
index 3dbe0e3..9e2fc2b 100644 (file)
@@ -76,6 +76,7 @@ LOCAL_SRC_FILES := \
        SyncFeatures.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+       libnativeloader \
        libbinder \
        libcutils \
        libEGL \
index 99b74bf..ab824d3 100644 (file)
 #define LOG_TAG "GraphicsEnv"
 #include <gui/GraphicsEnv.h>
 
+#include <mutex>
+
 #include <log/log.h>
+#include <nativeloader/dlext_namespaces.h>
 
 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
index d2e28ff..b7d6791 100644 (file)
@@ -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)
index 2555272..741a0ce 100644 (file)
 #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"
 
@@ -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<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;
     }