From d836ab005a3fd70e477a01d4200483131a285c9a Mon Sep 17 00:00:00 2001
From: Dimitry Ivanov <dimitry@google.com>
Date: Wed, 2 Nov 2016 18:03:10 -0700
Subject: [PATCH] Allow different namespace types for different classloaders

An app should be able to make cross-arch calls to different apps
via other app's Context.getClassLoader()

Bug: 32542970
Test: Boot fugu. Check that there are no linker-namespace
      related errors in the log.

Change-Id: I1593f4688bcde0121a5e24a707441a4935fa7dc4
---
 include/nativebridge/native_bridge.h         |  4 ++--
 libnativebridge/native_bridge.cc             |  6 +++---
 libnativebridge/tests/DummyNativeBridge3.cpp |  2 +-
 libnativeloader/native_loader.cpp            | 18 +++++++++++-------
 4 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h
index 26556f048..45266dedf 100644
--- a/include/nativebridge/native_bridge.h
+++ b/include/nativebridge/native_bridge.h
@@ -104,7 +104,7 @@ int NativeBridgeUnloadLibrary(void* handle);
 
 // Get last error message of native bridge when fail to load library or search symbol.
 // This is reflection of dlerror() for native bridge.
-char* NativeBridgeGetError();
+const char* NativeBridgeGetError();
 
 struct native_bridge_namespace_t;
 
@@ -244,7 +244,7 @@ struct NativeBridgeCallbacks {
   // Returns:
   //   A string describing the most recent error that occurred when load library
   //   or lookup symbol via native bridge.
-  char* (*getError)();
+  const char* (*getError)();
 
   // Check whether library paths are supported by native bridge.
   //
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 43e6c0a5b..eafc53d8d 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -551,15 +551,15 @@ int NativeBridgeUnloadLibrary(void* handle) {
   return -1;
 }
 
-char* NativeBridgeGetError() {
+const char* NativeBridgeGetError() {
   if (NativeBridgeInitialized()) {
     if (isCompatibleWith(NAMESPACE_VERSION)) {
       return callbacks->getError();
     } else {
-      ALOGE("not compatible with version %d, cannot get message", NAMESPACE_VERSION);
+      return "native bridge implementation is not compatible with version 3, cannot get message";
     }
   }
-  return nullptr;
+  return "native bridge is not initialized";
 }
 
 bool NativeBridgeIsPathSupported(const char* path) {
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
index c538fa071..13fce8599 100644
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ b/libnativebridge/tests/DummyNativeBridge3.cpp
@@ -68,7 +68,7 @@ extern "C" int native_bridge3_unloadLibrary(void* /* handle */) {
   return 0;
 }
 
-extern "C" char* native_bridge3_getError() {
+extern "C" const char* native_bridge3_getError() {
   return nullptr;
 }
 
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index e09cce3e3..15fe0540e 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -308,13 +308,17 @@ class LibraryNamespaces {
     // code is one example) unknown to linker in which  case linker uses anonymous
     // namespace. The second argument specifies the search path for the anonymous
     // namespace which is the library_path of the classloader.
-    if (!is_native_bridge) {
-      initialized_ = android_init_namespaces(public_libraries_.c_str(), library_path);
-      if (!initialized_) {
-        *error_msg = dlerror();
-      }
-    } else {
-      initialized_ = NativeBridgeInitNamespace(public_libraries_.c_str(), library_path);
+    initialized_ = android_init_namespaces(public_libraries_.c_str(),
+                                           is_native_bridge ? nullptr : library_path);
+    if (!initialized_) {
+      *error_msg = dlerror();
+      return false;
+    }
+
+    // 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();
       }