Propagate hiddenapi cmdline flags in OatFileAssistant::Dex2Oat

ART can invoke dex2oat on an out-of-date or non-existent oat file.
This code path will ignore any runtime hidden API enforcement policy
settings. Change the code to set the correct flag and add a gtest
for it.

Bug: 79680013
Test: make test-art-host-gtest-oat_file_assistant_test
Change-Id: Id6aa5e45d11626facb590621d43e2c52b9269b12
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 8e21fd3..580224e 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -95,6 +95,22 @@
   }
 }
 
+class ScopedHiddenApiEnforcementPolicySetting {
+ public:
+  explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
+      : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
+    Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
+  }
+
+  ~ScopedHiddenApiEnforcementPolicySetting() {
+    Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
+  }
+
+ private:
+  const EnforcementPolicy initial_policy_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
+};
+
 // Implementation details. DO NOT ACCESS DIRECTLY.
 namespace detail {
 
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 7d69927..4880d83 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -36,6 +36,7 @@
 #include "exec_utils.h"
 #include "gc/heap.h"
 #include "gc/space/image_space.h"
+#include "hidden_api.h"
 #include "image.h"
 #include "oat.h"
 #include "runtime.h"
@@ -823,6 +824,11 @@
     argv.push_back("--compiler-filter=verify-none");
   }
 
+  if (runtime->GetHiddenApiEnforcementPolicy() != hiddenapi::EnforcementPolicy::kNoChecks) {
+    argv.push_back("--runtime-arg");
+    argv.push_back("-Xhidden-api-checks");
+  }
+
   if (runtime->MustRelocateIfPossible()) {
     argv.push_back("--runtime-arg");
     argv.push_back("-Xrelocate");
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 99bc0b2..0b3c61d 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -33,6 +33,7 @@
 #include "class_loader_context.h"
 #include "common_runtime_test.h"
 #include "dexopt_test.h"
+#include "hidden_api.h"
 #include "oat_file.h"
 #include "oat_file_manager.h"
 #include "scoped_thread_state_change-inl.h"
@@ -43,6 +44,8 @@
 static const std::string kSpecialSharedLibrary = "&";  // NOLINT [runtime/string] [4]
 static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr;
 
+static constexpr char kDex2oatCmdLineHiddenApiArg[] = " --runtime-arg -Xhidden-api-checks";
+
 class OatFileAssistantTest : public DexoptTest {
  public:
   void VerifyOptimizationStatus(const std::string& file,
@@ -1413,6 +1416,46 @@
       oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
 }
 
+TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiDisabled) {
+  hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+      hiddenapi::EnforcementPolicy::kNoChecks);
+
+  std::string dex_location = GetScratchDir() + "/TestDexHiddenApiDisabled.jar";
+  Copy(GetDexSrc1(), dex_location);
+
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  std::string error_msg;
+  int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
+  EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
+
+  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+  EXPECT_NE(nullptr, oat_file.get());
+
+  const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
+  EXPECT_NE(nullptr, cmd_line);
+  EXPECT_EQ(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
+}
+
+TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiEnabled) {
+  hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+      hiddenapi::EnforcementPolicy::kBlacklistOnly);
+
+  std::string dex_location = GetScratchDir() + "/TestDexHiddenApiEnabled.jar";
+  Copy(GetDexSrc1(), dex_location);
+
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  std::string error_msg;
+  int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
+  EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
+
+  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+  EXPECT_NE(nullptr, oat_file.get());
+
+  const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
+  EXPECT_NE(nullptr, cmd_line);
+  EXPECT_NE(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
+}
+
 TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
   std::string dex_location = GetScratchDir() + "/TestDex.jar";
   std::string context_location = GetScratchDir() + "/ContextDex.jar";
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index b79334a..4843061 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -282,26 +282,9 @@
 }
 #undef STRING_INIT_LIST
 
-class ScopedHiddenApiExemption {
- public:
-  explicit ScopedHiddenApiExemption(Runtime* runtime)
-      : runtime_(runtime),
-        initial_policy_(runtime_->GetHiddenApiEnforcementPolicy()) {
-    runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kNoChecks);
-  }
-
-  ~ScopedHiddenApiExemption() {
-    runtime_->SetHiddenApiEnforcementPolicy(initial_policy_);
-  }
-
- private:
-  Runtime* runtime_;
-  const hiddenapi::EnforcementPolicy initial_policy_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiExemption);
-};
-
 void WellKnownClasses::Init(JNIEnv* env) {
-  ScopedHiddenApiExemption hiddenapi_exemption(Runtime::Current());
+  hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
+      hiddenapi::EnforcementPolicy::kNoChecks);
 
   dalvik_annotation_optimization_CriticalNative =
       CacheClass(env, "dalvik/annotation/optimization/CriticalNative");