Transfer ClassLoaderContext to the caller of OatFileAssistant::Create.

mast@ pointed out that the owned object adds complexity to
OatFileAssistant. Full discussion here: ag/19066608.

Bug: 229268202
Test: m test-art-host-gtest-art_runtime_tests
Change-Id: Iadcd5f5f090808d8dbbb6449ba9fc32832d99756
Merged-In: Ia8f320d1375985bbb6239822a90e6f95a9774bb5
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index f7c9e03..b69d2af 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -242,22 +242,23 @@
     bool load_executable,
     bool only_load_trusted_executable,
     std::unique_ptr<RuntimeOptions> runtime_options,
-    std::string* error_msg) {
+    /*out*/ std::unique_ptr<ClassLoaderContext>* context,
+    /*out*/ std::string* error_msg) {
   InstructionSet isa = GetInstructionSetFromString(isa_str.c_str());
   if (isa == InstructionSet::kNone) {
     *error_msg = StringPrintf("Instruction set '%s' is invalid", isa_str.c_str());
     return nullptr;
   }
 
-  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str.c_str());
-  if (context == nullptr) {
+  std::unique_ptr<ClassLoaderContext> tmp_context = ClassLoaderContext::Create(context_str.c_str());
+  if (tmp_context == nullptr) {
     *error_msg = StringPrintf("Class loader context '%s' is invalid", context_str.c_str());
     return nullptr;
   }
 
-  if (!context->OpenDexFiles(android::base::Dirname(filename.c_str()),
-                             /*context_fds=*/{},
-                             /*only_read_checksums=*/true)) {
+  if (!tmp_context->OpenDexFiles(android::base::Dirname(filename.c_str()),
+                                 /*context_fds=*/{},
+                                 /*only_read_checksums=*/true)) {
     *error_msg =
         StringPrintf("Failed to load class loader context files for '%s' with context '%s'",
                      filename.c_str(),
@@ -267,12 +268,12 @@
 
   auto assistant = std::make_unique<OatFileAssistant>(filename.c_str(),
                                                       isa,
-                                                      context.get(),
+                                                      tmp_context.get(),
                                                       load_executable,
                                                       only_load_trusted_executable,
                                                       std::move(runtime_options));
 
-  assistant->owned_context_ = std::move(context);
+  *context = std::move(tmp_context);
   return assistant;
 }
 
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 1198832..abbd896 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -157,15 +157,18 @@
                    int zip_fd);
 
   // A convenient factory function that accepts ISA, class loader context, and compiler filter in
-  // strings. Returns the created instance on success, or returns nullptr and outputs an error
-  // message if it fails to parse the input strings.
-  static std::unique_ptr<OatFileAssistant> Create(const std::string& filename,
-                                                  const std::string& isa_str,
-                                                  const std::string& context_str,
-                                                  bool load_executable,
-                                                  bool only_load_trusted_executable,
-                                                  std::unique_ptr<RuntimeOptions> runtime_options,
-                                                  std::string* error_msg);
+  // strings. Returns the created instance and ClassLoaderContext on success, or returns nullptr and
+  // outputs an error message if it fails to parse the input strings.
+  // The returned ClassLoaderContext must live at least as long as the OatFileAssistant.
+  static std::unique_ptr<OatFileAssistant> Create(
+      const std::string& filename,
+      const std::string& isa_str,
+      const std::string& context_str,
+      bool load_executable,
+      bool only_load_trusted_executable,
+      std::unique_ptr<RuntimeOptions> runtime_options,
+      /*out*/ std::unique_ptr<ClassLoaderContext>* context,
+      /*out*/ std::string* error_msg);
 
   // Returns true if the dex location refers to an element of the boot class
   // path.
@@ -471,7 +474,6 @@
   std::string dex_location_;
 
   ClassLoaderContext* context_;
-  std::unique_ptr<ClassLoaderContext> owned_context_;
 
   // Whether or not the parent directory of the dex file is writable.
   bool dex_parent_writable_ = false;
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index e414e4e..87fe2cb 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -1785,6 +1785,7 @@
 
   auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
 
+  std::unique_ptr<ClassLoaderContext> context;
   std::string error_msg;
   std::unique_ptr<OatFileAssistant> oat_file_assistant =
       OatFileAssistant::Create(dex_location,
@@ -1793,6 +1794,7 @@
                                /*load_executable=*/false,
                                /*only_load_trusted_executable=*/true,
                                MaybeCreateRuntimeOptions(),
+                               &context,
                                &error_msg);
   ASSERT_NE(oat_file_assistant, nullptr);
 
@@ -1808,6 +1810,7 @@
 
   auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
 
+  std::unique_ptr<ClassLoaderContext> context;
   std::string error_msg;
   EXPECT_EQ(OatFileAssistant::Create(dex_location,
                                      /*isa_str=*/"foo",
@@ -1815,6 +1818,7 @@
                                      /*load_executable=*/false,
                                      /*only_load_trusted_executable=*/true,
                                      MaybeCreateRuntimeOptions(),
+                                     &context,
                                      &error_msg),
             nullptr);
   EXPECT_EQ(error_msg, "Instruction set 'foo' is invalid");
@@ -1828,6 +1832,7 @@
 
   auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
 
+  std::unique_ptr<ClassLoaderContext> context;
   std::string error_msg;
   EXPECT_EQ(OatFileAssistant::Create(dex_location,
                                      GetInstructionSetString(kRuntimeISA),
@@ -1835,6 +1840,7 @@
                                      /*load_executable=*/false,
                                      /*only_load_trusted_executable=*/true,
                                      MaybeCreateRuntimeOptions(),
+                                     &context,
                                      &error_msg),
             nullptr);
   EXPECT_EQ(error_msg, "Class loader context 'foo' is invalid");
@@ -1853,6 +1859,7 @@
 
   auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
 
+  std::unique_ptr<ClassLoaderContext> context;
   std::string error_msg;
   EXPECT_EQ(OatFileAssistant::Create(dex_location,
                                      GetInstructionSetString(kRuntimeISA),
@@ -1860,6 +1867,7 @@
                                      /*load_executable=*/false,
                                      /*only_load_trusted_executable=*/true,
                                      MaybeCreateRuntimeOptions(),
+                                     &context,
                                      &error_msg),
             nullptr);
   EXPECT_EQ(error_msg,