Merge changes I5e33e5bf,I64237006
* changes:
Make android_load_sphal_library thread-safe
Switch libvndksupport's linker.c to C++
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index e5b536c..f4544a1 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -3,7 +3,7 @@
cc_library {
name: "libvndksupport",
native_bridge_supported: true,
- srcs: ["linker.c"],
+ srcs: ["linker.cpp"],
cflags: [
"-Wall",
"-Werror",
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
deleted file mode 100644
index 84c2132..0000000
--- a/libvndksupport/linker.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "linker.h"
-
-#include <android/dlext.h>
-#include <dlfcn.h>
-
-#define LOG_TAG "vndksupport"
-#include <log/log.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-__attribute__((weak)) extern struct android_namespace_t* android_get_exported_namespace(const char*);
-__attribute__((weak)) extern void* android_dlopen_ext(const char*, int, const android_dlextinfo*);
-
-static const char* namespace_name = NULL;
-
-static struct android_namespace_t* get_vendor_namespace() {
- const char* namespace_names[] = {"sphal", "default", NULL};
- static struct android_namespace_t* vendor_namespace = NULL;
- if (vendor_namespace == NULL) {
- int name_idx = 0;
- while (namespace_names[name_idx] != NULL) {
- if (android_get_exported_namespace != NULL) {
- vendor_namespace = android_get_exported_namespace(namespace_names[name_idx]);
- }
- if (vendor_namespace != NULL) {
- namespace_name = namespace_names[name_idx];
- break;
- }
- name_idx++;
- }
- }
- return vendor_namespace;
-}
-
-int android_is_in_vendor_process() {
- // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
- // loaded (sysprop service isn't up for init to know <ver>).
- if (getpid() == 1) {
- return 0;
- }
- if (android_get_exported_namespace == NULL) {
- ALOGD("android_get_exported_namespace() not available. Assuming system process.");
- return 0;
- }
-
- // In vendor process, 'vndk' namespace is not visible, whereas in system
- // process, it is.
- return android_get_exported_namespace("vndk") == NULL;
-}
-
-void* android_load_sphal_library(const char* name, int flag) {
- struct android_namespace_t* vendor_namespace = get_vendor_namespace();
- if (vendor_namespace != NULL) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = vendor_namespace,
- };
- void* handle = NULL;
- if (android_dlopen_ext != NULL) {
- handle = android_dlopen_ext(name, flag, &dlextinfo);
- }
- if (!handle) {
- ALOGE("Could not load %s from %s namespace: %s.", name, namespace_name, dlerror());
- }
- return handle;
- } else {
- ALOGD("Loading %s from current namespace instead of sphal namespace.", name);
- return dlopen(name, flag);
- }
-}
-
-int android_unload_sphal_library(void* handle) {
- return dlclose(handle);
-}
diff --git a/libvndksupport/linker.cpp b/libvndksupport/linker.cpp
new file mode 100644
index 0000000..cf0f618
--- /dev/null
+++ b/libvndksupport/linker.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "vndksupport"
+
+#include "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <log/log.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <initializer_list>
+
+__attribute__((weak)) extern "C" android_namespace_t* android_get_exported_namespace(const char*);
+__attribute__((weak)) extern "C" void* android_dlopen_ext(const char*, int,
+ const android_dlextinfo*);
+
+namespace {
+
+struct VendorNamespace {
+ android_namespace_t* ptr = nullptr;
+ const char* name = nullptr;
+};
+
+} // anonymous namespace
+
+static VendorNamespace get_vendor_namespace() {
+ static VendorNamespace result = ([] {
+ for (const char* name : {"sphal", "default"}) {
+ if (android_get_exported_namespace != nullptr) {
+ if (android_namespace_t* ns = android_get_exported_namespace(name)) {
+ return VendorNamespace{ns, name};
+ }
+ }
+ }
+ return VendorNamespace{};
+ })();
+ return result;
+}
+
+int android_is_in_vendor_process() {
+ // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
+ // loaded (sysprop service isn't up for init to know <ver>).
+ if (getpid() == 1) {
+ return 0;
+ }
+ if (android_get_exported_namespace == nullptr) {
+ ALOGD("android_get_exported_namespace() not available. Assuming system process.");
+ return 0;
+ }
+
+ // In vendor process, 'vndk' namespace is not visible, whereas in system
+ // process, it is.
+ return android_get_exported_namespace("vndk") == nullptr;
+}
+
+void* android_load_sphal_library(const char* name, int flag) {
+ VendorNamespace vendor_namespace = get_vendor_namespace();
+ if (vendor_namespace.ptr != nullptr) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = vendor_namespace.ptr,
+ };
+ void* handle = nullptr;
+ if (android_dlopen_ext != nullptr) {
+ handle = android_dlopen_ext(name, flag, &dlextinfo);
+ }
+ if (!handle) {
+ ALOGE("Could not load %s from %s namespace: %s.", name, vendor_namespace.name,
+ dlerror());
+ }
+ return handle;
+ } else {
+ ALOGD("Loading %s from current namespace instead of sphal namespace.", name);
+ return dlopen(name, flag);
+ }
+}
+
+int android_unload_sphal_library(void* handle) {
+ return dlclose(handle);
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
index 7ce27d4..d0c8ef7 100644
--- a/libvndksupport/tests/linker_test.cpp
+++ b/libvndksupport/tests/linker_test.cpp
@@ -21,11 +21,6 @@
#include <vndksupport/linker.h>
#include <string>
-// Since the test executable will be in /data and ld.config.txt does not
-// configure sphal namespace for executables in /data, the call to
-// android_load_sphal_library will always fallback to the plain dlopen from the
-// default namespace.
-
// Let's use libEGL_<chipset>.so as a SP-HAL in test
static std::string find_sphal_lib() {
const char* path =