ART: Add option to use stderr logger

Add a runtime option that sets the android-base logger to StderrLogger,
forcing all further logging to go to stderr. This can be used for
better interaction with dalvikvm or dex2oat on-device.

Bug: 72998814
Test: m test-art-target-gtest-dex2oat_test
Change-Id: I18794bbed0885810f8f0480816b1c780753a9702
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index d0b0d49..f917318 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1667,4 +1667,21 @@
   }
 }
 
+TEST_F(Dex2oatTest, StderrLoggerOutput) {
+  std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
+  std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
+
+  // Test file doesn't matter.
+  Copy(GetDexSrc1(), dex_location);
+
+  GenerateOdexForTest(dex_location,
+                      odex_location,
+                      CompilerFilter::kQuicken,
+                      { "--runtime-arg", "-Xuse-stderr-logger" },
+                      true);
+  // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
+  // even on device.
+  EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
+}
+
 }  // namespace art
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 92eb703..72346cc 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -332,6 +332,8 @@
           .IntoKey(M::TargetSdkVersion)
       .Define("-Xno-hidden-api-checks")
           .IntoKey(M::NoHiddenApiChecks)
+      .Define("-Xuse-stderr-logger")
+          .IntoKey(M::UseStderrLogger)
       .Ignore({
           "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
           "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index b26b09c..5381bb3 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1082,10 +1082,16 @@
   // Take a snapshot of the environment at the time the runtime was created, for use by Exec, etc.
   env_snapshot_.TakeSnapshot();
 
-  RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
+  using Opt = RuntimeArgumentMap;
+  Opt runtime_options(std::move(runtime_options_in));
   ScopedTrace trace(__FUNCTION__);
   CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
 
+  // Early override for logging output.
+  if (runtime_options.Exists(Opt::UseStderrLogger)) {
+    android::base::SetLogger(android::base::StderrLogger);
+  }
+
   MemMap::Init();
 
   // Try to reserve a dedicated fault page. This is allocated for clobbered registers and sentinels.
@@ -1112,7 +1118,6 @@
     }
   }
 
-  using Opt = RuntimeArgumentMap;
   VLOG(startup) << "Runtime::Init -verbose:startup enabled";
 
   QuasiAtomic::Startup();
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index e78d952..4831d7d 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -150,5 +150,6 @@
 RUNTIME_OPTIONS_KEY (bool,                SlowDebug,                      false)
 
 RUNTIME_OPTIONS_KEY (unsigned int,        GlobalRefAllocStackTraceLimit,  0)  // 0 = off
+RUNTIME_OPTIONS_KEY (Unit,                UseStderrLogger)
 
 #undef RUNTIME_OPTIONS_KEY