Merge "Allow vendors to extend the list of public libs"
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index d38bdd2..3ffabc3 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -20,9 +20,11 @@
#include <dirent.h>
#include <dlfcn.h>
+#include <fcntl.h>
#include <jni.h>
#include <JNIHelp.h>
#include <libgen.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -32,17 +34,18 @@
#include <unordered_set>
#include <vector>
-static std::vector<std::string> kDefaultLibraryPaths = {
-#if defined(__LP64__)
- "/system/lib64",
- "/vendor/lib64",
-#else
- "/system/lib",
- "/vendor/lib",
-#endif
- };
+#include "ScopedLocalRef.h"
+#include "ScopedUtfChars.h"
-static std::unordered_set<std::string> kPublicLibraries = {
+#if defined(__LP64__)
+static const std::string kSystemLibraryPath = "/system/lib64";
+static const std::string kVendorLibraryPath = "/vendor/lib64";
+#else
+static const std::string kSystemLibraryPath = "/system/lib";
+static const std::string kVendorLibraryPath = "/vendor/lib";
+#endif
+
+static std::unordered_set<std::string> kSystemPublicLibraries = {
"libandroid.so",
"libc.so",
"libdl.so",
@@ -89,10 +92,12 @@
return true;
}
-static bool should_be_accessible(const std::string& path) {
+static bool should_be_accessible(const std::string& public_library_path,
+ const std::unordered_set<std::string>& public_libraries,
+ const std::string& path) {
std::string name = basename(path.c_str());
- return (kPublicLibraries.find(name) != kPublicLibraries.end()) &&
- (kDefaultLibraryPaths.front() + "/" + name == path);
+ return (public_libraries.find(name) != public_libraries.end()) &&
+ (public_library_path + "/" + name == path);
}
static bool is_directory(const std::string path) {
@@ -105,17 +110,19 @@
}
static bool is_libdl(const std::string path) {
- return kDefaultLibraryPaths.front() + "/libdl.so" == path;
+ return kSystemLibraryPath + "/libdl.so" == path;
}
-extern "C" JNIEXPORT jstring JNICALL Java_android_jni_cts_LinkerNamespacesHelper_runAccessibilityTest(
- JNIEnv* env, jclass clazz __attribute__((unused))) {
- std::list<std::string> dirs(kDefaultLibraryPaths.begin(), kDefaultLibraryPaths.end());
+static bool check_libs(const std::string& public_library_path,
+ const std::unordered_set<std::string>& public_libraries,
+ std::string* error) {
+ std::list<std::string> dirs;
+ dirs.push_back(public_library_path);
+
while (!dirs.empty()) {
const auto dir = dirs.front();
dirs.pop_front();
- std::string error;
- bool success = for_each_file(dir, [&dirs,&dir](const char* name, std::string* error_msg) {
+ bool success = for_each_file(dir, [&](const char* name, std::string* error_msg) {
std::string path = dir + "/" + name;
if (is_directory(path)) {
dirs.push_back(path);
@@ -132,7 +139,7 @@
auto dlcloser = [](void* handle) { dlclose(handle); };
std::unique_ptr<void, decltype(dlcloser)> handle(dlopen(path.c_str(), RTLD_NOW), dlcloser);
- if (should_be_accessible(path)) {
+ if (should_be_accessible(public_library_path, public_libraries, path)) {
if (handle.get() == nullptr) {
*error_msg = "The library \"" + path + "\" should be accessible but isn't: " + dlerror();
return false;
@@ -151,13 +158,44 @@
}
}
return true;
- }, &error);
+ }, error);
if (!success) {
- return env->NewStringUTF(error.c_str());
+ return false;
}
}
+ return true;
+}
+
+static void load_vendor_libraries(JNIEnv* env,
+ jobjectArray java_vendor_public_libraries,
+ std::unordered_set<std::string>* libraries) {
+ size_t size = env->GetArrayLength(java_vendor_public_libraries);
+ for (size_t i = 0; i<size; ++i) {
+ ScopedLocalRef<jstring> java_soname(
+ env, (jstring) env->GetObjectArrayElement(java_vendor_public_libraries, i));
+
+ ScopedUtfChars soname(env, java_soname.get());
+ libraries->insert(soname.c_str());
+ }
+}
+
+extern "C" JNIEXPORT jstring JNICALL
+ Java_android_jni_cts_LinkerNamespacesHelper_runAccessibilityTestImpl(
+ JNIEnv* env,
+ jclass clazz __attribute__((unused)),
+ jobjectArray java_vendor_public_libraries) {
+ std::string error;
+
+ std::unordered_set<std::string> vendor_public_libraries;
+ load_vendor_libraries(env, java_vendor_public_libraries, &vendor_public_libraries);
+
+ if (!check_libs(kSystemLibraryPath, kSystemPublicLibraries, &error) ||
+ !check_libs(kVendorLibraryPath, vendor_public_libraries, &error)) {
+ return env->NewStringUTF(error.c_str());
+ }
+
return nullptr;
}
diff --git a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
index 8a91c44..91ebe73 100644
--- a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
+++ b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
@@ -16,6 +16,7 @@
package android.jni.cts;
+import java.io.IOException;
/**
* Basic static method tests. The "nonce" class being tested by this
@@ -34,7 +35,7 @@
* Test library accessibility. Internal platform libraries should not
* be accessible from the jni code.
*/
- public void test_linker_namespaces() {
+ public void test_linker_namespaces() throws IOException {
String error = LinkerNamespacesHelper.runAccessibilityTest();
if (error != null) {
fail(error);
diff --git a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
index 2dff019..21bd71a 100644
--- a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
+++ b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
@@ -16,6 +16,31 @@
package android.jni.cts;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.List;
+
class LinkerNamespacesHelper {
- public static native String runAccessibilityTest();
+ private final static String VENDOR_CONFIG_FILE = "/vendor/etc/public.libraries.txt";
+ public static String runAccessibilityTest() throws IOException {
+ List<String> libs = new ArrayList<>();
+ File file = new File(VENDOR_CONFIG_FILE);
+ if (file.exists()) {
+ try (BufferedReader br = new BufferedReader(new FileReader(file))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.isEmpty() || line.startsWith("#")) {
+ continue;
+ }
+ libs.add(line);
+ }
+ }
+ }
+ return runAccessibilityTestImpl(libs.toArray(new String[libs.size()]));
+ }
+ private static native String runAccessibilityTestImpl(String[] publicVendorLibs);
}