Fix link apex for jni libs

When library_path is ":" splitted list of .jar files, we should iterate
over each .jar file path to link a proper APEX namespace for JNI lib.

Bug: 169826971
Test: libnativeloader_test
Test: move libicing to appsearch apex
Change-Id: I3df47203d336036d0e015f9c5421b30a0377087f
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
index 2360819..8b87338 100644
--- a/libnativeloader/library_namespaces.cpp
+++ b/libnativeloader/library_namespaces.cpp
@@ -344,15 +344,17 @@
     }
   }
 
-  auto apex_ns_name = FindApexNamespaceName(dex_path);
-  if (apex_ns_name.ok()) {
-    const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
-    if (jni_libs != "") {
-      auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
-      if (apex_ns.ok()) {
-        linked = app_ns->Link(&apex_ns.value(), jni_libs);
-        if (!linked.ok()) {
-          return linked.error();
+  for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) {
+    auto apex_ns_name = FindApexNamespaceName(each_jar_path);
+    if (apex_ns_name.ok()) {
+      const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
+      if (jni_libs != "") {
+        auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
+        if (apex_ns.ok()) {
+          linked = app_ns->Link(&apex_ns.value(), jni_libs);
+          if (!linked.ok()) {
+            return linked.error();
+          }
         }
       }
     }
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
index 79e5070..c1dd4aa 100644
--- a/libnativeloader/native_loader_test.cpp
+++ b/libnativeloader/native_loader_test.cpp
@@ -188,6 +188,7 @@
   bool expected_link_with_platform_ns = true;
   bool expected_link_with_art_ns = true;
   bool expected_link_with_i18n_ns = true;
+  bool expected_link_with_conscrypt_ns = false;
   bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
   bool expected_link_with_vndk_ns = false;
   bool expected_link_with_vndk_product_ns = false;
@@ -196,6 +197,7 @@
   std::string expected_shared_libs_to_platform_ns = default_public_libraries();
   std::string expected_shared_libs_to_art_ns = apex_public_libraries().at("com_android_art");
   std::string expected_shared_libs_to_i18n_ns = apex_public_libraries().at("com_android_i18n");
+  std::string expected_shared_libs_to_conscrypt_ns = apex_jni_libraries("com_android_conscrypt");
   std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
   std::string expected_shared_libs_to_vndk_ns = vndksp_libraries_vendor();
   std::string expected_shared_libs_to_vndk_product_ns = vndksp_libraries_product();
@@ -255,6 +257,11 @@
                                               StrEq(expected_shared_libs_to_neuralnetworks_ns)))
           .WillOnce(Return(true));
     }
+    if (expected_link_with_conscrypt_ns) {
+      EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_conscrypt"),
+                                              StrEq(expected_shared_libs_to_conscrypt_ns)))
+          .WillOnce(Return(true));
+    }
   }
 
   void RunTest() {
@@ -336,6 +343,17 @@
   RunTest();
 }
 
+TEST_P(NativeLoaderTest_Create, SystemServerWithApexJars) {
+  dex_path = "/system/framework/services.jar:/apex/com.android.conscrypt/javalib/service-foo.jar";
+  is_shared = true;
+
+  expected_namespace_name = "classloader-namespace-shared";
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_link_with_conscrypt_ns = true;
+  SetExpectations();
+  RunTest();
+}
+
 TEST_P(NativeLoaderTest_Create, UnbundledProductApp) {
   dex_path = "/product/app/foo/foo.apk";
   is_shared = false;
diff --git a/libnativeloader/native_loader_test.h b/libnativeloader/native_loader_test.h
index cab18da..09c56e5 100644
--- a/libnativeloader/native_loader_test.h
+++ b/libnativeloader/native_loader_test.h
@@ -80,6 +80,11 @@
   NAMESPACE_ENTRY("com_android_i18n"),
   NAMESPACE_ENTRY("com_android_neuralnetworks"),
   NAMESPACE_ENTRY("com_android_art"),
+
+  // TODO(b/191644631) This can be removed when the test becomes more test-friendly.
+  // This is added so that the test can exercise the JNI lib related behavior.
+  NAMESPACE_ENTRY("com_android_conscrypt"),
+
   NAMESPACE_ENTRY("default"),
   NAMESPACE_ENTRY("sphal"),
   NAMESPACE_ENTRY("system"),