Use shared namespaces for bundled apps

Shared namespaces clone the list of loaded native
libraries from the caller namespace. This allows
classloaders for bundled apps to share already loaded
libraries with default namespace.

Bug: http://b/26165097
Bug: http://b/22548808
Change-Id: Ia90b603a0ca97194618b82fb191d6790a4b1f281
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 5ab55e0..8d60be2 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -220,7 +220,8 @@
 
   std::string reason;
   ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
-                  LoadNativeLibrary(env_, "", class_loader_, nullptr, nullptr, &reason))
+                  LoadNativeLibrary(env_, "", class_loader_, /* is_shared_namespace */ false,
+                                    nullptr, nullptr, &reason))
       << reason;
 
   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
@@ -235,7 +236,8 @@
 
   std::string reason;
   ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
-                  LoadNativeLibrary(env_, "", class_loader_, nullptr, nullptr, &reason))
+                  LoadNativeLibrary(env_, "", class_loader_, /* is_shared_namespace */ false,
+                                    nullptr, nullptr, &reason))
       << reason;
 
   jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 15f5122..5c44193 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -717,8 +717,8 @@
 }
 
 bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
-                                  jstring library_path, jstring permitted_path,
-                                  std::string* error_msg) {
+                                  bool is_shared_namespace, jstring library_path,
+                                  jstring permitted_path, std::string* error_msg) {
   error_msg->clear();
 
   // See if we've already loaded this library.  If we have, and the class loader
@@ -777,8 +777,9 @@
 
   Locks::mutator_lock_->AssertNotHeld(self);
   const char* path_str = path.empty() ? nullptr : path.c_str();
-  void* handle = android::OpenNativeLibrary(env, runtime_->GetTargetSdkVersion(),
-                                            path_str, class_loader, library_path, permitted_path);
+  void* handle = android::OpenNativeLibrary(env, runtime_->GetTargetSdkVersion(), path_str,
+                                            class_loader, is_shared_namespace, library_path,
+                                            permitted_path);
   bool needs_native_bridge = false;
   if (handle == nullptr) {
     if (android::NativeBridgeIsSupported(path_str)) {
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 8559769..8cae1e5 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -85,8 +85,9 @@
    * Returns 'true' on success. On failure, sets 'error_msg' to a
    * human-readable description of the error.
    */
-  bool LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject javaLoader,
-                         jstring library_path, jstring permitted_path, std::string* error_msg);
+  bool LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
+                         bool is_shared_namespace, jstring library_path, jstring permitted_path,
+                         std::string* error_msg);
 
   // Unload native libraries with cleared class loaders.
   void UnloadNativeLibraries()
diff --git a/runtime/native/OpenjdkJvm.cc b/runtime/native/OpenjdkJvm.cc
index 7e7711e..66ee9fb 100644
--- a/runtime/native/OpenjdkJvm.cc
+++ b/runtime/native/OpenjdkJvm.cc
@@ -356,7 +356,8 @@
 
 
 JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env, jstring javaFilename, jobject javaLoader,
-                                 jstring javaLdLibraryPath, jstring javaLibraryPermittedPath) {
+                                 jboolean isSharedNamespace, jstring javaLibrarySearchPath,
+                                 jstring javaLibraryPermittedPath) {
   ScopedUtfChars filename(env, javaFilename);
   if (filename.c_str() == NULL) {
     return NULL;
@@ -368,7 +369,7 @@
   // linker namespace instead of global LD_LIBRARY_PATH
   // (23 is Marshmallow)
   if (target_sdk_version <= 23) {
-    SetLdLibraryPath(env, javaLdLibraryPath);
+    SetLdLibraryPath(env, javaLibrarySearchPath);
   }
 
   std::string error_msg;
@@ -376,8 +377,13 @@
     art::ScopedObjectAccess soa(env);
     art::StackHandleScope<1> hs(soa.Self());
     art::JavaVMExt* vm = art::Runtime::Current()->GetJavaVM();
-    bool success = vm->LoadNativeLibrary(env, filename.c_str(), javaLoader,
-                                         javaLdLibraryPath, javaLibraryPermittedPath, &error_msg);
+    bool success = vm->LoadNativeLibrary(env,
+                                         filename.c_str(),
+                                         javaLoader,
+                                         isSharedNamespace == JNI_TRUE,
+                                         javaLibrarySearchPath,
+                                         javaLibraryPermittedPath,
+                                         &error_msg);
     if (success) {
       return nullptr;
     }
diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc
index 4a1e6c2..f42a17d 100644
--- a/runtime/native/java_lang_Runtime.cc
+++ b/runtime/native/java_lang_Runtime.cc
@@ -68,7 +68,8 @@
 }
 
 static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader,
-                                  jstring javaLdLibraryPath, jstring javaIsolationPath) {
+                                  jboolean isSharedNamespace, jstring javaLibrarySearchPath,
+                                  jstring javaLibraryPermittedPath) {
   ScopedUtfChars filename(env, javaFilename);
   if (filename.c_str() == nullptr) {
     return nullptr;
@@ -80,14 +81,19 @@
   // linker namespace instead of global LD_LIBRARY_PATH
   // (23 is Marshmallow)
   if (target_sdk_version <= INT_MAX) {
-    SetLdLibraryPath(env, javaLdLibraryPath);
+    SetLdLibraryPath(env, javaLibrarySearchPath);
   }
 
   std::string error_msg;
   {
     JavaVMExt* vm = Runtime::Current()->GetJavaVM();
-    bool success = vm->LoadNativeLibrary(env, filename.c_str(), javaLoader,
-                                         javaLdLibraryPath, javaIsolationPath, &error_msg);
+    bool success = vm->LoadNativeLibrary(env,
+                                         filename.c_str(),
+                                         javaLoader,
+                                         isSharedNamespace == JNI_TRUE,
+                                         javaLibrarySearchPath,
+                                         javaLibraryPermittedPath,
+                                         &error_msg);
     if (success) {
       return nullptr;
     }
@@ -115,7 +121,7 @@
   NATIVE_METHOD(Runtime, gc, "()V"),
   NATIVE_METHOD(Runtime, maxMemory, "!()J"),
   NATIVE_METHOD(Runtime, nativeExit, "(I)V"),
-  NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
+  NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;ZLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
   NATIVE_METHOD(Runtime, totalMemory, "!()J"),
 };
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c7a5456..a7ba220 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1224,13 +1224,17 @@
   // libcore can't because it's the library that implements System.loadLibrary!
   {
     std::string error_msg;
-    if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr, nullptr, nullptr, &error_msg)) {
+    if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr,
+                                     /* is_shared_namespace */ false,
+                                     nullptr, nullptr, &error_msg)) {
       LOG(FATAL) << "LoadNativeLibrary failed for \"libjavacore.so\": " << error_msg;
     }
   }
   {
     std::string error_msg;
-    if (!java_vm_->LoadNativeLibrary(env, "libopenjdk.so", nullptr, nullptr, nullptr, &error_msg)) {
+    if (!java_vm_->LoadNativeLibrary(env, "libopenjdk.so", nullptr,
+                                     /* is_shared_namespace */ false,
+                                     nullptr, nullptr, &error_msg)) {
       LOG(FATAL) << "LoadNativeLibrary failed for \"libopenjdk.so\": " << error_msg;
     }
   }
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 2094b5f..8300921 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -383,7 +383,7 @@
   ScopedLocalRef<jclass> java_lang_Runtime(env, env->FindClass("java/lang/Runtime"));
   java_lang_Runtime_nativeLoad =
       CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad",
-                  "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)"
+                  "(Ljava/lang/String;Ljava/lang/ClassLoader;ZLjava/lang/String;Ljava/lang/String;)"
                       "Ljava/lang/String;");
 }