Revert^2 "Support shared libraries in CreateContextFromClassLoader."

This reverts commit 1717a493a4a0c1c3b69ecfcb58838627b4c75878.

bug: 120036590
bug: 120031686

Reason for revert: Fix code to ensure ownership of dex files.

Change-Id: I99fffb52b73e0a41d779a41605ddf2e9249c02e0
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 991faa2..9b2e1a1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -9116,8 +9116,8 @@
     Thread* self,
     const std::vector<const DexFile*>& dex_files,
     Handle<mirror::Class> loader_class,
-    Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries,
-    Handle<mirror::ClassLoader> parent_loader) {
+    Handle<mirror::ClassLoader> parent_loader,
+    Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries) {
 
   StackHandleScope<5> hs(self);
 
@@ -9246,7 +9246,8 @@
 jobject ClassLinker::CreateWellKnownClassLoader(Thread* self,
                                                 const std::vector<const DexFile*>& dex_files,
                                                 jclass loader_class,
-                                                jobject parent_loader) {
+                                                jobject parent_loader,
+                                                jobject shared_libraries) {
   CHECK(self->GetJniEnv()->IsSameObject(loader_class,
                                         WellKnownClasses::dalvik_system_PathClassLoader) ||
         self->GetJniEnv()->IsSameObject(loader_class,
@@ -9257,24 +9258,21 @@
   ScopedObjectAccessUnchecked soa(self);
 
   // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
-  StackHandleScope<3> hs(self);
+  StackHandleScope<4> hs(self);
 
   Handle<mirror::Class> h_loader_class =
       hs.NewHandle<mirror::Class>(soa.Decode<mirror::Class>(loader_class));
-  Handle<mirror::ClassLoader> parent =
-      hs.NewHandle<mirror::ClassLoader>(ObjPtr<mirror::ClassLoader>::DownCast(
-          (parent_loader != nullptr)
-              ? soa.Decode<mirror::ClassLoader>(parent_loader)
-              : nullptr));
-  Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries =
-      hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr);
+  Handle<mirror::ClassLoader> h_parent =
+      hs.NewHandle<mirror::ClassLoader>(soa.Decode<mirror::ClassLoader>(parent_loader));
+  Handle<mirror::ObjectArray<mirror::ClassLoader>> h_shared_libraries =
+      hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::ClassLoader>>(shared_libraries));
 
   ObjPtr<mirror::ClassLoader> loader = CreateWellKnownClassLoader(
       self,
       dex_files,
       h_loader_class,
-      shared_libraries,
-      parent);
+      h_parent,
+      h_shared_libraries);
 
   // Make it a global ref and return.
   ScopedLocalRef<jobject> local_ref(
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 15a7204..dd5f911 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -574,7 +574,8 @@
   jobject CreateWellKnownClassLoader(Thread* self,
                                      const std::vector<const DexFile*>& dex_files,
                                      jclass loader_class,
-                                     jobject parent_loader)
+                                     jobject parent_loader,
+                                     jobject shared_libraries = nullptr)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
@@ -591,8 +592,8 @@
       Thread* self,
       const std::vector<const DexFile*>& dex_files,
       Handle<mirror::Class> loader_class,
-      Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries,
-      Handle<mirror::ClassLoader> parent_loader)
+      Handle<mirror::ClassLoader> parent_loader,
+      Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries)
           REQUIRES_SHARED(Locks::mutator_lock_)
           REQUIRES(!Locks::dex_lock_);
 
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 029db7e..c5988f6 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -695,8 +695,8 @@
           self,
           class_path_files,
           loader_class,
-          libraries,
-          parent);
+          parent,
+          libraries);
   if (for_shared_library) {
     canonicalized_libraries[FlattenClasspath(info.classpath)] =
         map_scope.NewHandle<mirror::ClassLoader>(loader);
@@ -914,10 +914,12 @@
 // the classpath.
 // This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the
 // BootClassLoader. Note that the class loader chain is expected to be short.
-bool ClassLoaderContext::AddInfoToContextFromClassLoader(
+bool ClassLoaderContext::CreateInfoFromClassLoader(
       ScopedObjectAccessAlreadyRunnable& soa,
       Handle<mirror::ClassLoader> class_loader,
-      Handle<mirror::ObjectArray<mirror::Object>> dex_elements)
+      Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
+      ClassLoaderInfo* child_info,
+      bool is_shared_library)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) {
     // Nothing to do for the boot class loader as we don't add its dex files to the context.
@@ -952,31 +954,52 @@
   }
 
   ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type);
-  if (class_loader_chain_ == nullptr) {
+  // Attach the `ClassLoaderInfo` now, before populating dex files, as only the
+  // `ClassLoaderContext` knows whether these dex files should be deleted or not.
+  if (child_info == nullptr) {
     class_loader_chain_.reset(info);
+  } else if (is_shared_library) {
+    child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
   } else {
-    ClassLoaderInfo* child = class_loader_chain_.get();
-    while (child->parent != nullptr) {
-      child = child->parent.get();
-    }
-    child->parent.reset(info);
+    child_info->parent.reset(info);
   }
 
+  // Now that `info` is in the chain, populate dex files.
   for (const DexFile* dex_file : dex_files_loaded) {
     info->classpath.push_back(dex_file->GetLocation());
     info->checksums.push_back(dex_file->GetLocationChecksum());
     info->opened_dex_files.emplace_back(dex_file);
   }
 
-  // We created the ClassLoaderInfo for the current loader. Move on to its parent.
-
-  StackHandleScope<1> hs(Thread::Current());
-  Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
-
   // Note that dex_elements array is null here. The elements are considered to be part of the
   // current class loader and are not passed to the parents.
   ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements;
-  return AddInfoToContextFromClassLoader(soa, parent, null_dex_elements);
+
+  // Add the shared libraries.
+  StackHandleScope<3> hs(Thread::Current());
+  ArtField* field =
+      jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
+  ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
+  if (raw_shared_libraries != nullptr) {
+    Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries =
+        hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>());
+    MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
+    for (int32_t i = 0; i < shared_libraries->GetLength(); ++i) {
+      temp_loader.Assign(shared_libraries->Get(i));
+      if (!CreateInfoFromClassLoader(
+              soa, temp_loader, null_dex_elements, info, /*is_shared_library=*/ true)) {
+        return false;
+      }
+    }
+  }
+
+  // We created the ClassLoaderInfo for the current loader. Move on to its parent.
+  Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
+  if (!CreateInfoFromClassLoader(
+          soa, parent, null_dex_elements, info, /*is_shared_library=*/ false)) {
+    return false;
+  }
+  return true;
 }
 
 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader(
@@ -990,13 +1013,12 @@
       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
   Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
       hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
-
   std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false));
-  if (result->AddInfoToContextFromClassLoader(soa, h_class_loader, h_dex_elements)) {
-    return result;
-  } else {
+  if (!result->CreateInfoFromClassLoader(
+          soa, h_class_loader, h_dex_elements, nullptr, /*is_shared_library=*/ false)) {
     return nullptr;
   }
+  return result;
 }
 
 static bool IsAbsoluteLocation(const std::string& location) {
@@ -1130,8 +1152,8 @@
 
   if (info.shared_libraries.size() != expected_info.shared_libraries.size()) {
     LOG(WARNING) << "ClassLoaderContext shared library size mismatch. "
-          << "Expected=" << expected_info.classpath.size()
-          << ", found=" << info.classpath.size()
+          << "Expected=" << expected_info.shared_libraries.size()
+          << ", found=" << info.shared_libraries.size()
           << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
     return false;
   }
diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h
index 71f40ac..5a89c4e 100644
--- a/runtime/class_loader_context.h
+++ b/runtime/class_loader_context.h
@@ -227,12 +227,14 @@
   // of the call.
   void CheckDexFilesOpened(const std::string& calling_method) const;
 
-  // Adds the `class_loader` info to the context.
+  // Creates the `ClassLoaderInfo` representing`class_loader` and attach it to `this`.
   // The dex file present in `dex_elements` array (if not null) will be added at the end of
   // the classpath.
-  bool AddInfoToContextFromClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
-                                       Handle<mirror::ClassLoader> class_loader,
-                                       Handle<mirror::ObjectArray<mirror::Object>> dex_elements)
+  bool CreateInfoFromClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
+                                 Handle<mirror::ClassLoader> class_loader,
+                                 Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
+                                 ClassLoaderInfo* child_info,
+                                 bool is_shared_library)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Encodes the context as a string suitable to be passed to dex2oat or to be added to the
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index 0756982..3c5f1ef 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -23,6 +23,7 @@
 #include "base/dchecked_vector.h"
 #include "base/stl_util.h"
 #include "class_linker.h"
+#include "class_root.h"
 #include "common_runtime_test.h"
 #include "dex/dex_file.h"
 #include "handle_scope-inl.h"
@@ -30,6 +31,7 @@
 #include "mirror/class.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
+#include "mirror/object_array-alloc-inl.h"
 #include "oat_file_assistant.h"
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
@@ -1230,4 +1232,30 @@
             ClassLoaderContext::VerificationResult::kVerifies);
 }
 
+TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderWithSharedLibraries) {
+  jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
+
+  ScopedObjectAccess soa(Thread::Current());
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
+    mirror::ObjectArray<mirror::ClassLoader>::Alloc(
+        soa.Self(),
+        GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
+        1));
+  libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
+
+  jobject class_loader_b = LoadDexInPathClassLoader(
+      "ForClassLoaderB", nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
+
+  std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
+  ASSERT_TRUE(context != nullptr);
+  std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ForClassLoaderB");
+  VerifyClassLoaderPCL(context.get(), 0, dex_files[0]->GetLocation());
+  dex_files = OpenTestDexFiles("ForClassLoaderA");
+  VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, dex_files[0]->GetLocation());
+
+  ASSERT_EQ(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")),
+            ClassLoaderContext::VerificationResult::kVerifies);
+}
+
 }  // namespace art
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 7388c2e..0300fa1 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -273,7 +273,8 @@
 
 jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& dex_name,
                                                              jclass loader_class,
-                                                             jobject parent_loader) {
+                                                             jobject parent_loader,
+                                                             jobject shared_libraries) {
   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name.c_str());
   std::vector<const DexFile*> class_path;
   CHECK_NE(0U, dex_files.size());
@@ -288,7 +289,8 @@
       self,
       class_path,
       loader_class,
-      parent_loader);
+      parent_loader,
+      shared_libraries);
 
   {
     // Verify we build the correct chain.
@@ -315,10 +317,12 @@
 }
 
 jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::string& dex_name,
-                                                        jobject parent_loader) {
+                                                        jobject parent_loader,
+                                                        jobject shared_libraries) {
   return LoadDexInWellKnownClassLoader(dex_name,
                                        WellKnownClasses::dalvik_system_PathClassLoader,
-                                       parent_loader);
+                                       parent_loader,
+                                       shared_libraries);
 }
 
 jobject CommonRuntimeTestImpl::LoadDexInDelegateLastClassLoader(const std::string& dex_name,
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index c48ab36..0fee797 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -115,11 +115,14 @@
   jobject LoadMultiDex(const char* first_dex_name, const char* second_dex_name)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  jobject LoadDexInPathClassLoader(const std::string& dex_name, jobject parent_loader);
+  jobject LoadDexInPathClassLoader(const std::string& dex_name,
+                                   jobject parent_loader,
+                                   jobject shared_libraries = nullptr);
   jobject LoadDexInDelegateLastClassLoader(const std::string& dex_name, jobject parent_loader);
   jobject LoadDexInWellKnownClassLoader(const std::string& dex_name,
                                         jclass loader_class,
-                                        jobject parent_loader);
+                                        jobject parent_loader,
+                                        jobject shared_libraries = nullptr);
 
   std::unique_ptr<Runtime> runtime_;