Merge "libgrallocusage: use gralloc1.h usage flags" into oc-dev
diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h
index 45266de..929b8ae 100644
--- a/include/nativebridge/native_bridge.h
+++ b/include/nativebridge/native_bridge.h
@@ -116,14 +116,25 @@
 // Use NativeBridgeIsSupported() instead in non-namespace scenario.
 bool NativeBridgeIsPathSupported(const char* path);
 
-// Initializes public and anonymous namespace at native bridge side.
+// Initializes anonymous namespace.
+// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
+//
+// The anonymous namespace is used in the case when a NativeBridge implementation
+// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
+// by dynamic linker; for example calls from the mono-compiled code.
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Should not use in non-namespace scenario.
-bool NativeBridgeInitNamespace(const char* public_ns_sonames,
-                               const char* anon_ns_library_path);
+bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
+                                        const char* anon_ns_library_path);
 
-// Create a namespace and pass the key of related namespaces to native bridge.
+// Create new namespace in which native libraries will be loaded.
+// NativeBridge's peer of android_create_namespace() of dynamic linker.
+//
+// The libraries in the namespace are searched by folowing order:
+// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
+// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
+// 3. deault_library_path (This of this as namespace-local default library path)
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Should not use in non-namespace scenario.
@@ -134,7 +145,17 @@
                                                        const char* permitted_when_isolated_path,
                                                        native_bridge_namespace_t* parent_ns);
 
+// Creates a link which shares some libraries from one namespace to another.
+// NativeBridge's peer of android_link_namespaces() of dynamic linker.
+//
+// Starting with v3, NativeBridge has two scenarios: with/without namespace.
+// Should not use in non-namespace scenario.
+bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+                                const char* shared_libs_sonames);
+
 // Load a shared library with namespace key that is supported by the native bridge.
+// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
+// extension.
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
@@ -152,7 +173,7 @@
   // Parameters:
   //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
   // Returns:
-  //   true iff initialization was successful.
+  //   true if initialization was successful.
   bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
                      const char* instruction_set);
 
@@ -194,10 +215,10 @@
   // instruction set.
   //
   // Parameters:
-  //    instruction_set [IN] the instruction set of the app
+  //   instruction_set [IN] the instruction set of the app
   // Returns:
-  //    NULL if not supported by native bridge.
-  //    Otherwise, return all environment values to be set after fork.
+  //   NULL if not supported by native bridge.
+  //   Otherwise, return all environment values to be set after fork.
   const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);
 
   // Added callbacks in version 2.
@@ -206,9 +227,9 @@
   // forwards- or backwards-compatible, and libnativebridge will then stop using it.
   //
   // Parameters:
-  //     bridge_version [IN] the version of libnativebridge.
+  //   bridge_version [IN] the version of libnativebridge.
   // Returns:
-  //     true iff the native bridge supports the given version of libnativebridge.
+  //   true if the native bridge supports the given version of libnativebridge.
   bool (*isCompatibleWith)(uint32_t bridge_version);
 
   // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
@@ -217,12 +238,12 @@
   // that will potentially lead to cycles.
   //
   // Parameters:
-  //     signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
+  //   signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
   //                 supported by the runtime.
   // Returns:
-  //     NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
-  //     runtime.
-  //     Otherwise, a pointer to the signal handler.
+  //   NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
+  //   runtime.
+  //   Otherwise, a pointer to the signal handler.
   NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal);
 
   // Added callbacks in version 3.
@@ -231,7 +252,7 @@
   // to zero then the dynamic library is unloaded.
   //
   // Parameters:
-  //     handle [IN] the handler of a dynamic library.
+  //   handle [IN] the handler of a dynamic library.
   //
   // Returns:
   //   0 on success, and nonzero on error.
@@ -257,33 +278,36 @@
   // Use isSupported instead in non-namespace scenario.
   bool (*isPathSupported)(const char* library_path);
 
-  // Initializes anonymous namespace at native bridge side and pass the key of
-  // two namespaces(default and anonymous) owned by dynamic linker to native bridge.
+  // Initializes anonymous namespace at native bridge side.
+  // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
+  //
+  // The anonymous namespace is used in the case when a NativeBridge implementation
+  // cannot identify the caller of dlopen/dlsym which happens for the code not loaded
+  // by dynamic linker; for example calls from the mono-compiled code.
   //
   // Parameters:
-  //     public_ns_sonames [IN] the name of "public" libraries.
-  //     anon_ns_library_path [IN] the library search path of (anonymous) namespace.
+  //   public_ns_sonames [IN] the name of "public" libraries.
+  //   anon_ns_library_path [IN] the library search path of (anonymous) namespace.
   // Returns:
-  //     true if the pass is ok.
-  //     Otherwise, false.
+  //   true if the pass is ok.
+  //   Otherwise, false.
   //
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Should not use in non-namespace scenario.
-  bool (*initNamespace)(const char* public_ns_sonames,
-                        const char* anon_ns_library_path);
+  bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
 
-
-  // Create a namespace and pass the key of releated namespaces to native bridge.
+  // Create new namespace in which native libraries will be loaded.
+  // NativeBridge's peer of android_create_namespace() of dynamic linker.
   //
   // Parameters:
-  //     name [IN] the name of the namespace.
-  //     ld_library_path [IN] the first set of library search paths of the namespace.
-  //     default_library_path [IN] the second set of library search path of the namespace.
-  //     type [IN] the attribute of the namespace.
-  //     permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is).
-  //     parent_ns [IN] the pointer of the parent namespace to be inherited from.
+  //   name [IN] the name of the namespace.
+  //   ld_library_path [IN] the first set of library search paths of the namespace.
+  //   default_library_path [IN] the second set of library search path of the namespace.
+  //   type [IN] the attribute of the namespace.
+  //   permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is).
+  //   parent_ns [IN] the pointer of the parent namespace to be inherited from.
   // Returns:
-  //     native_bridge_namespace_t* for created namespace or nullptr in the case of error.
+  //   native_bridge_namespace_t* for created namespace or nullptr in the case of error.
   //
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Should not use in non-namespace scenario.
@@ -294,7 +318,25 @@
                                                 const char* permitted_when_isolated_path,
                                                 native_bridge_namespace_t* parent_ns);
 
+  // Creates a link which shares some libraries from one namespace to another.
+  // NativeBridge's peer of android_link_namespaces() of dynamic linker.
+  //
+  // Parameters:
+  //   from [IN] the namespace where libraries are accessed.
+  //   to [IN] the namespace where libraries are loaded.
+  //   shared_libs_sonames [IN] the libraries to be shared.
+  //
+  // Returns:
+  //   Whether successed or not.
+  //
+  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
+  // Should not use in non-namespace scenario.
+  bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+                         const char* shared_libs_sonames);
+
   // Load a shared library within a namespace.
+  // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
+  // extension.
   //
   // Parameters:
   //   libpath [IN] path to the shared library
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index fdcf22f..b19a2fd 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -35,22 +35,13 @@
 
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
+#include <private/fs_config.h>
 #include <utils/Compat.h>
 
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
 
-/* The following structure is stored little endian */
-struct fs_path_config_from_file {
-    uint16_t len;
-    uint16_t mode;
-    uint16_t uid;
-    uint16_t gid;
-    uint64_t capabilities;
-    char prefix[];
-} __attribute__((__aligned__(sizeof(uint64_t))));
-
 /* My kingdom for <endian.h> */
 static inline uint16_t get2LE(const uint8_t* src) { return src[0] | (src[1] << 8); }
 
@@ -236,21 +227,24 @@
     /* clang-format on */
 };
 
+static size_t strip(const char* path, size_t len, const char suffix[]) {
+    if (len < strlen(suffix)) return len;
+    if (strncmp(path + len - strlen(suffix), suffix, strlen(suffix))) return len;
+    return len - strlen(suffix);
+}
+
 static int fs_config_open(int dir, int which, const char* target_out_path) {
     int fd = -1;
 
     if (target_out_path && *target_out_path) {
         /* target_out_path is the path to the directory holding content of
-         * system partition but as we cannot guaranty it ends with '/system'
-         * we need this below skip_len logic */
+         * system partition but as we cannot guarantee it ends with '/system'
+         * or with or without a trailing slash, need to strip them carefully. */
         char* name = NULL;
-        int target_out_path_len = strlen(target_out_path);
-        int skip_len = strlen("/system");
-
-        if (target_out_path[target_out_path_len] == '/') {
-            skip_len++;
-        }
-        if (asprintf(&name, "%s%s", target_out_path, conf[which][dir] + skip_len) != -1) {
+        size_t len = strlen(target_out_path);
+        len = strip(target_out_path, len, "/");
+        len = strip(target_out_path, len, "/system");
+        if (asprintf(&name, "%.*s%s", (int)len, target_out_path, conf[which][dir]) != -1) {
             fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
             free(name);
         }
diff --git a/libcutils/include/private/fs_config.h b/libcutils/include/private/fs_config.h
new file mode 100644
index 0000000..7dad668
--- /dev/null
+++ b/libcutils/include/private/fs_config.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _LIBS_CUTILS_PRIVATE_FS_CONFIG_H
+#define _LIBS_CUTILS_PRIVATE_FS_CONFIG_H
+
+#include <stdint.h>
+
+/*
+ * binary format for the runtime <partition>/etc/fs_config_(dirs|files)
+ * filesystem override files.
+ */
+
+/* The following structure is stored little endian */
+struct fs_path_config_from_file {
+    uint16_t len;
+    uint16_t mode;
+    uint16_t uid;
+    uint16_t gid;
+    uint64_t capabilities;
+    char prefix[];
+} __attribute__((__aligned__(sizeof(uint64_t))));
+
+#endif /* _LIBS_CUTILS_PRIVATE_FS_CONFIG_H */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index bb8c3af..bc262db 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -107,14 +107,16 @@
     license: "NOTICE",
 }
 
-cc_library_headers {
-    name: "liblog_vndk_headers",
-    export_include_dirs: ["include_vndk"],
-}
-
 ndk_library {
     name: "liblog.ndk",
     symbol_file: "liblog.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
+
+llndk_library {
+    name: "liblog.llndk",
+    symbol_file: "liblog.map.txt",
+    unversioned: true,
+    export_include_dirs: ["include_vndk"],
+}
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 599dc90..c00f2a0 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -1,6 +1,10 @@
 LIBLOG {
   global:
+    android_name_to_log_id; # vndk
+    android_log_id_to_name; # vndk
     __android_log_assert;
+    __android_log_buf_print; # vndk
+    __android_log_buf_write; # vndk
     __android_log_print;
     __android_log_vprint;
     __android_log_write;
@@ -8,8 +12,27 @@
     *;
 };
 
+LIBLOG_L {
+  global:
+    android_logger_clear; # vndk
+    android_logger_get_id; # vndk
+    android_logger_get_log_readable_size; # vndk
+    android_logger_get_log_version; # vndk
+    android_logger_get_log_size; # vndk
+    android_logger_list_alloc; # vndk
+    android_logger_list_alloc_time; # vndk
+    android_logger_list_free; # vndk
+    android_logger_list_open; # vndk
+    android_logger_list_read; # vndk
+    android_logger_open; # vndk
+    android_logger_set_log_size; # vndk
+};
+
 LIBLOG_M {
   global:
+    android_logger_get_prune_list; # vndk
+    android_logger_set_prune_list; # vndk
+    android_logger_get_statistics; # vndk
     __android_log_is_loggable;
 };
 
diff --git a/liblog/properties.c b/liblog/properties.c
index 0b0ef52..adf1900 100644
--- a/liblog/properties.c
+++ b/liblog/properties.c
@@ -95,7 +95,7 @@
   /* calculate the size of our key temporary buffer */
   const size_t taglen = tag ? len : 0;
   /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
-  char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
+  char key[sizeof(log_namespace) + taglen];
   char* kp;
   size_t i;
   char c = 0;
@@ -108,7 +108,8 @@
    * Where the missing tag matches all tags and becomes the
    * system global default. We do not support ro.log.tag* .
    */
-  static char last_tag[PROP_NAME_MAX];
+  static char* last_tag;
+  static size_t last_tag_len;
   static uint32_t global_serial;
   /* some compilers erroneously see uninitialized use. !not_locked */
   uint32_t current_global_serial = 0;
@@ -147,25 +148,29 @@
   if (taglen) {
     int local_change_detected = change_detected;
     if (!not_locked) {
-      if (!last_tag[0] || (last_tag[0] != tag[0]) ||
-          strncmp(
-              last_tag + 1, tag + 1,
-              (len < sizeof(last_tag)) ? (len - 1) : (sizeof(last_tag) - 1)) ||
-          ((len < sizeof(last_tag)) && last_tag[len])) {
+      if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
+          strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
         /* invalidate log.tag.<tag> cache */
         for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
           tag_cache[i].cache.pinfo = NULL;
           tag_cache[i].c = '\0';
         }
-        last_tag[0] = '\0';
+        if (last_tag) last_tag[0] = '\0';
         local_change_detected = 1;
       }
-      if (!last_tag[0]) {
-        if (len < sizeof(last_tag)) {
+      if (!last_tag || !last_tag[0]) {
+        if (!last_tag) {
+          last_tag = calloc(1, len + 1);
+          last_tag_len = 0;
+          if (last_tag) last_tag_len = len + 1;
+        } else if (len >= last_tag_len) {
+          last_tag = realloc(last_tag, len + 1);
+          last_tag_len = 0;
+          if (last_tag) last_tag_len = len + 1;
+        }
+        if (last_tag) {
           strncpy(last_tag, tag, len);
           last_tag[len] = '\0';
-        } else {
-          strncpy(last_tag, tag, sizeof(last_tag));
         }
       }
     }
@@ -435,7 +440,7 @@
                                                            int flag) {
   struct cache_property property = { { NULL, -1 }, { 0 } };
   if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
-    char newkey[PROP_NAME_MAX];
+    char newkey[strlen("persist.") + strlen(key) + 1];
     snprintf(newkey, sizeof(newkey), "ro.%s", key);
     refresh_cache_property(&property, newkey);
     property.cache.pinfo = NULL;
@@ -600,8 +605,8 @@
     evaluate_property_get_size
     /* clang-format on */
   };
-  char key_persist[PROP_NAME_MAX];
-  char key_ro[PROP_NAME_MAX];
+  char key_persist[strlen(global_tunable) + strlen(".security") + 1];
+  char key_ro[strlen(global_default) + strlen(".security") + 1];
   struct cache2_property_size local = {
     /* clang-format off */
     PTHREAD_MUTEX_INITIALIZER, 0,
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 83f35b1..7976f67 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -573,17 +573,17 @@
   return false;
 }
 
-bool NativeBridgeInitNamespace(const char* public_ns_sonames,
-                               const char* anon_ns_library_path) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path);
-    } else {
-      ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
+bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
+                                        const char* anon_ns_library_path) {
+    if (NativeBridgeInitialized()) {
+        if (isCompatibleWith(NAMESPACE_VERSION)) {
+            return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
+        } else {
+            ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
+        }
     }
-  }
 
-  return false;
+    return false;
 }
 
 native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
@@ -608,6 +608,19 @@
   return nullptr;
 }
 
+bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+                                const char* shared_libs_sonames) {
+    if (NativeBridgeInitialized()) {
+        if (isCompatibleWith(NAMESPACE_VERSION)) {
+            return callbacks->linkNamespaces(from, to, shared_libs_sonames);
+        } else {
+            ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
+        }
+    }
+
+    return false;
+}
+
 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
   if (NativeBridgeInitialized()) {
     if (isCompatibleWith(NAMESPACE_VERSION)) {
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 4c3e862..c9468f0 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -24,7 +24,7 @@
     NativeBridge3UnloadLibrary_test.cpp \
     NativeBridge3GetError_test.cpp \
     NativeBridge3IsPathSupported_test.cpp \
-    NativeBridge3InitNamespace_test.cpp \
+    NativeBridge3InitAnonymousNamespace_test.cpp \
     NativeBridge3CreateNamespace_test.cpp \
     NativeBridge3LoadLibraryExt_test.cpp
 
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
index 13fce85..b0dd6d0 100644
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ b/libnativebridge/tests/DummyNativeBridge3.cpp
@@ -76,9 +76,9 @@
   return true;
 }
 
-extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */,
-                                        const char* /* anon_ns_library_path */) {
-  return true;
+extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
+                                                      const char* /* anon_ns_library_path */) {
+    return true;
 }
 
 extern "C" android::native_bridge_namespace_t*
@@ -91,30 +91,34 @@
   return nullptr;
 }
 
+extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
+                                              android::native_bridge_namespace_t* /* to */,
+                                              const char* /* shared_libs_soname */) {
+    return true;
+}
+
 extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
                                                int /* flag */,
                                                android::native_bridge_namespace_t* /* ns */) {
   return nullptr;
 }
 
-
-android::NativeBridgeCallbacks NativeBridgeItf {
-  // v1
-  .version = 3,
-  .initialize = &native_bridge3_initialize,
-  .loadLibrary = &native_bridge3_loadLibrary,
-  .getTrampoline = &native_bridge3_getTrampoline,
-  .isSupported = &native_bridge3_isSupported,
-  .getAppEnv = &native_bridge3_getAppEnv,
-  // v2
-  .isCompatibleWith = &native_bridge3_isCompatibleWith,
-  .getSignalHandler = &native_bridge3_getSignalHandler,
-  // v3
-  .unloadLibrary = &native_bridge3_unloadLibrary,
-  .getError = &native_bridge3_getError,
-  .isPathSupported  = &native_bridge3_isPathSupported,
-  .initNamespace = &native_bridge3_initNamespace,
-  .createNamespace = &native_bridge3_createNamespace,
-  .loadLibraryExt = &native_bridge3_loadLibraryExt
-};
-
+android::NativeBridgeCallbacks NativeBridgeItf{
+    // v1
+    .version = 3,
+    .initialize = &native_bridge3_initialize,
+    .loadLibrary = &native_bridge3_loadLibrary,
+    .getTrampoline = &native_bridge3_getTrampoline,
+    .isSupported = &native_bridge3_isSupported,
+    .getAppEnv = &native_bridge3_getAppEnv,
+    // v2
+    .isCompatibleWith = &native_bridge3_isCompatibleWith,
+    .getSignalHandler = &native_bridge3_getSignalHandler,
+    // v3
+    .unloadLibrary = &native_bridge3_unloadLibrary,
+    .getError = &native_bridge3_getError,
+    .isPathSupported = &native_bridge3_isPathSupported,
+    .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
+    .createNamespace = &native_bridge3_createNamespace,
+    .linkNamespaces = &native_bridge3_linkNamespaces,
+    .loadLibraryExt = &native_bridge3_loadLibraryExt};
diff --git a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
similarity index 90%
rename from libnativebridge/tests/NativeBridge3InitNamespace_test.cpp
rename to libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
index ae0fd2b..989a819 100644
--- a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp
+++ b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
@@ -20,7 +20,7 @@
 
 constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
 
-TEST_F(NativeBridgeTest, V3_InitNamespace) {
+TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
     ASSERT_TRUE(NativeBridgeAvailable());
@@ -30,7 +30,7 @@
     ASSERT_TRUE(NativeBridgeAvailable());
 
     ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr));
+    ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
 
     // Clean-up code_cache
     ASSERT_EQ(0, rmdir(kCodeCache));
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 74f2f1d..ebd6d4b 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -183,6 +183,11 @@
         return false;
       }
 
+      if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
+          *error_msg = NativeBridgeGetError();
+          return false;
+      }
+
       native_loader_ns = NativeLoaderNamespace(ns);
     }
 
@@ -324,10 +329,10 @@
 
     // and now initialize native bridge namespaces if necessary.
     if (NativeBridgeInitialized()) {
-      initialized_ = NativeBridgeInitNamespace(public_libraries_.c_str(),
-                                               is_native_bridge ? library_path : nullptr);
-      if (!initialized_) {
-        *error_msg = NativeBridgeGetError();
+        initialized_ = NativeBridgeInitAnonymousNamespace(
+            public_libraries_.c_str(), is_native_bridge ? library_path : nullptr);
+        if (!initialized_) {
+            *error_msg = NativeBridgeGetError();
       }
     }