libnativeloader_test: link non-public libs statically

Non-public NDK libs are not supposed to be tested in CTS. Specifically
native-bridged execution (e.g. arm on x86) doesn't support this.

The awkward thing here is that the test redefines all libnativebridge
symbols, but still links shared libnativebridge to call its
OpenSystemLibrary. Due to symbols duplication we cannot simply convert
libnativebridge to static. Instead, as a quick fix, we copy OpenSystemLibrary
implementation from native_bridge.cpp. We expect that one of the
codebase owners will find a better way to share OpenSystemLibrary later.

Test: cts-tradefed run cts -m libnativeloader_tests (arm on x86)
Bug: b/268440713
Change-Id: I7c651200567a299742e7604ee07b043713ca1fec
Merged-In: I7c651200567a299742e7604ee07b043713ca1fec
(cherry picked from commit b2b067192ac047b99c0d03104c5d7dbf79192ef1)
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index e14aea2..0e63892 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -159,10 +159,22 @@
     srcs: [
         "native_loader_api_test.c",
         "native_loader_test.cpp",
+        "open_system_library.cpp",
     ],
-    shared_libs: [
+    static_libs: [
+        "libbase",
         "libnativeloader",
     ],
+    shared_libs: [
+        "liblog",
+    ],
+    target: {
+        android: {
+            static_libs: [
+                "libPlatformProperties",
+            ],
+        },
+    },
 
     // Support multilib variants (using different suffix per sub-architecture), which is needed on
     // build targets with secondary architectures, as the CTS test suite packaging logic flattens
diff --git a/libnativeloader/open_system_library.cpp b/libnativeloader/open_system_library.cpp
new file mode 100644
index 0000000..63175aa
--- /dev/null
+++ b/libnativeloader/open_system_library.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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 "nativeloader_test"
+
+#include <dlfcn.h>
+#include <log/log.h>
+
+#ifdef ART_TARGET_ANDROID
+#include "nativeloader/dlext_namespaces.h"
+#endif
+
+namespace android {
+
+extern "C" {
+
+// TODO(b/268440756): Find a way to reuse it from libnativebridge.
+void* OpenSystemLibrary(const char* path, int flags) {
+#ifdef ART_TARGET_ANDROID
+  // The system namespace is called "default" for binaries in /system and
+  // "system" for those in the Runtime APEX. Try "system" first since
+  // "default" always exists.
+  // TODO(b/185587109): Get rid of this error prone logic.
+  android_namespace_t* system_ns = android_get_exported_namespace("system");
+  if (system_ns == nullptr) {
+    system_ns = android_get_exported_namespace("default");
+    const char* message = "Failed to get system namespace for loading %s";
+    LOG_ALWAYS_FATAL_IF(system_ns == nullptr, message, path);
+  }
+  const android_dlextinfo dlextinfo = {
+      .flags = ANDROID_DLEXT_USE_NAMESPACE,
+      .library_namespace = system_ns,
+  };
+  return android_dlopen_ext(path, flags, &dlextinfo);
+#else
+  return dlopen(path, flags);
+#endif
+}
+
+}  // extern "C"
+
+}  // namespace android