Upgrade native bridge to version 3 to support namespace

Native bridge implements namespace related interfaces in version 3.
The namespace semantic here is same as Android dynamic linker's.
Native loader wraps library loading functions of dynamic linker and
native bridge. Thus, Android runtime is able to load native library
of different ISA on one device by calling native loader directly.

Bug: http://b/28242460
Test: mm && make test-art-host -j48
Change-Id: Idde2b9d99fb6ebe547407c716b5478a231f745a7
Signed-off-by: Zhenhua WANG <zhenhua.wang@intel.com>
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 32b2d27..43e6c0a 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -80,6 +80,19 @@
 // Current state of the native bridge.
 static NativeBridgeState state = NativeBridgeState::kNotSetup;
 
+// The version of NativeBridge implementation.
+// Different Nativebridge interface needs the service of different version of
+// Nativebridge implementation.
+// Used by isCompatibleWith() which is introduced in v2.
+enum NativeBridgeImplementationVersion {
+    // first version, not used.
+    DEFAULT_VERSION = 1,
+    // The version which signal semantic is introduced.
+    SIGNAL_VERSION = 2,
+    // The version which namespace semantic is introduced.
+    NAMESPACE_VERSION = 3,
+};
+
 // Whether we had an error at some point.
 static bool had_error = false;
 
@@ -100,8 +113,6 @@
 // and hard code the directory name again here.
 static constexpr const char* kCodeCacheDir = "code_cache";
 
-static constexpr uint32_t kLibNativeBridgeVersion = 2;
-
 // Characters allowed in a native bridge filename. The first character must
 // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-].
 static bool CharacterAllowed(char c, bool first) {
@@ -152,19 +163,18 @@
   }
 }
 
-static bool VersionCheck(const NativeBridgeCallbacks* cb) {
+// The policy of invoking Nativebridge changed in v3 with/without namespace.
+// Suggest Nativebridge implementation not maintain backward-compatible.
+static bool isCompatibleWith(const uint32_t version) {
   // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported
   // version.
-  if (cb == nullptr || cb->version == 0) {
+  if (callbacks == nullptr || callbacks->version == 0 || version == 0) {
     return false;
   }
 
   // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check.
-  if (cb->version >= 2) {
-    if (!callbacks->isCompatibleWith(kLibNativeBridgeVersion)) {
-      // TODO: Scan which version is supported, and fall back to handle it.
-      return false;
-    }
+  if (callbacks->version >= SIGNAL_VERSION) {
+    return callbacks->isCompatibleWith(version);
   }
 
   return true;
@@ -205,7 +215,7 @@
         callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
                                                                    kNativeBridgeInterfaceSymbol));
         if (callbacks != nullptr) {
-          if (VersionCheck(callbacks)) {
+          if (isCompatibleWith(NAMESPACE_VERSION)) {
             // Store the handle for later.
             native_bridge_handle = handle;
           } else {
@@ -520,8 +530,91 @@
 }
 
 NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
-  if (NativeBridgeInitialized() && callbacks->version >= 2) {
-    return callbacks->getSignalHandler(signal);
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(SIGNAL_VERSION)) {
+      return callbacks->getSignalHandler(signal);
+    } else {
+      ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION);
+    }
+  }
+  return nullptr;
+}
+
+int NativeBridgeUnloadLibrary(void* handle) {
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(NAMESPACE_VERSION)) {
+      return callbacks->unloadLibrary(handle);
+    } else {
+      ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION);
+    }
+  }
+  return -1;
+}
+
+char* NativeBridgeGetError() {
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(NAMESPACE_VERSION)) {
+      return callbacks->getError();
+    } else {
+      ALOGE("not compatible with version %d, cannot get message", NAMESPACE_VERSION);
+    }
+  }
+  return nullptr;
+}
+
+bool NativeBridgeIsPathSupported(const char* path) {
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(NAMESPACE_VERSION)) {
+      return callbacks->isPathSupported(path);
+    } else {
+      ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION);
+    }
+  }
+  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);
+    }
+  }
+
+  return false;
+}
+
+native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
+                                                       const char* ld_library_path,
+                                                       const char* default_library_path,
+                                                       uint64_t type,
+                                                       const char* permitted_when_isolated_path,
+                                                       native_bridge_namespace_t* parent_ns) {
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(NAMESPACE_VERSION)) {
+      return callbacks->createNamespace(name,
+                                        ld_library_path,
+                                        default_library_path,
+                                        type,
+                                        permitted_when_isolated_path,
+                                        parent_ns);
+    } else {
+      ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name);
+    }
+  }
+
+  return nullptr;
+}
+
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
+  if (NativeBridgeInitialized()) {
+    if (isCompatibleWith(NAMESPACE_VERSION)) {
+      return callbacks->loadLibraryExt(libpath, flag, ns);
+    } else {
+      ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION);
+    }
   }
   return nullptr;
 }