Set timeout by command line flag

Instead of deriving from --use-compilation-os implicitly, the client
should specify its desired timeout by command line flags.

Bug: 202830861
Test: atest ComposHostTestCases
Change-Id: Id47f80475639d952d055b4658ff89d153f0f4048
diff --git a/odrefresh/odr_config.h b/odrefresh/odr_config.h
index 402955c..3752107 100644
--- a/odrefresh/odr_config.h
+++ b/odrefresh/odr_config.h
@@ -29,6 +29,12 @@
 namespace art {
 namespace odrefresh {
 
+// Maximum execution time for odrefresh from start to end.
+constexpr time_t kMaximumExecutionSeconds = 300;
+
+// Maximum execution time for any child process spawned.
+constexpr time_t kMaxChildProcessSeconds = 90;
+
 // An enumeration of the possible zygote configurations on Android.
 enum class ZygoteKind : uint8_t {
   // 32-bit primary zygote, no secondary zygote.
@@ -57,6 +63,8 @@
   int compilation_os_address_ = 0;
   std::string boot_classpath_;
   std::string artifact_dir_;
+  time_t max_execution_seconds_ = kMaxChildProcessSeconds;
+  time_t max_child_process_seconds_ = kMaximumExecutionSeconds;
 
   // Staging directory for artifacts. The directory must exist and will be automatically removed
   // after compilation. If empty, use the default directory.
@@ -133,6 +141,8 @@
   const std::string& GetStagingDir() const {
     return staging_dir_;
   }
+  time_t GetMaxExecutionSeconds() const { return max_execution_seconds_; }
+  time_t GetMaxChildProcessSeconds() const { return max_child_process_seconds_; }
 
   void SetApexInfoListFile(const std::string& file_path) { apex_info_list_file_ = file_path; }
   void SetArtBinDir(const std::string& art_bin_dir) { art_bin_dir_ = art_bin_dir; }
@@ -148,6 +158,8 @@
   void SetDryRun() { dry_run_ = true; }
   void SetIsa(const InstructionSet isa) { isa_ = isa; }
   void SetCompilationOsAddress(int address) { compilation_os_address_ = address; }
+  void SetMaxExecutionSeconds(int seconds) { max_execution_seconds_ = seconds; }
+  void SetMaxChildProcessSeconds(int seconds) { max_child_process_seconds_ = seconds; }
 
   void SetSystemServerClasspath(const std::string& classpath) {
     system_server_classpath_ = classpath;
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index be58702..ebaf396 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -103,18 +103,6 @@
 // Name of cache info file in the ART Apex artifact cache.
 constexpr const char* kCacheInfoFile = "cache-info.xml";
 
-// Maximum execution time for odrefresh from start to end.
-constexpr time_t kMaximumExecutionSeconds = 300;
-
-// Extra execution time when running child processes in a VM.
-constexpr time_t kExtraExecutionSecondsInVm = 180;
-
-// Maximum execution time for any child process spawned.
-constexpr time_t kMaxChildProcessSeconds = 90;
-
-// Extra execution time for any child process spawned in a VM.
-constexpr time_t kExtraChildProcessSecondsInVm = 60;
-
 void EraseFiles(const std::vector<std::unique_ptr<File>>& files) {
   for (auto& file : files) {
     file->Erase(/*unlink=*/true);
@@ -496,17 +484,6 @@
 
   systemserver_compilable_jars_ = android::base::Split(config_.GetSystemServerClasspath(), ":");
   boot_classpath_jars_ = android::base::Split(config_.GetBootClasspath(), ":");
-
-  max_execution_seconds_ = kMaximumExecutionSeconds;
-  max_child_process_seconds_ = kMaxChildProcessSeconds;
-
-  if (config_.UseCompilationOs()) {
-    // Give extra time to all of the Comp OS cases for simplicity. But really, this is only needed
-    // on cuttlefish, where we run Comp OS in a slow, *nested* VM.
-    // TODO(197531822): Remove once we can give the VM more CPU and/or improve the file caching.
-    max_execution_seconds_ += kExtraExecutionSecondsInVm;
-    max_child_process_seconds_ += kExtraChildProcessSecondsInVm;
-  }
 }
 
 time_t OnDeviceRefresh::GetExecutionTimeUsed() const {
@@ -514,11 +491,11 @@
 }
 
 time_t OnDeviceRefresh::GetExecutionTimeRemaining() const {
-  return std::max(static_cast<time_t>(0), max_execution_seconds_ - GetExecutionTimeUsed());
+  return std::max(static_cast<time_t>(0), config_.GetMaxExecutionSeconds() - GetExecutionTimeUsed());
 }
 
 time_t OnDeviceRefresh::GetSubprocessTimeout() const {
-  return std::min(GetExecutionTimeRemaining(), max_child_process_seconds_);
+  return std::min(GetExecutionTimeRemaining(), config_.GetMaxChildProcessSeconds());
 }
 
 std::optional<std::vector<apex::ApexInfo>> OnDeviceRefresh::GetApexInfoList() const {
diff --git a/odrefresh/odrefresh.h b/odrefresh/odrefresh.h
index a3e5e17..0f7a724 100644
--- a/odrefresh/odrefresh.h
+++ b/odrefresh/odrefresh.h
@@ -178,9 +178,6 @@
 
   const time_t start_time_;
 
-  time_t max_execution_seconds_;
-  time_t max_child_process_seconds_;
-
   std::unique_ptr<ExecUtils> exec_utils_;
 
   std::unique_ptr<OdrDexopt> odr_dexopt_;
diff --git a/odrefresh/odrefresh_main.cc b/odrefresh/odrefresh_main.cc
index 7359df5..7cb770c 100644
--- a/odrefresh/odrefresh_main.cc
+++ b/odrefresh/odrefresh_main.cc
@@ -206,6 +206,18 @@
       art::OverrideDalvikCacheSubDirectory(value);
       config->SetArtifactDirectory(Concatenate(
           {android::base::Dirname(art::odrefresh::kOdrefreshArtifactDirectory), "/", value}));
+    } else if (ArgumentMatches(arg, "--max-execution-seconds=", &value)) {
+      int seconds;
+      if (!android::base::ParseInt(value, &seconds)) {
+        ArgumentError("Failed to parse integer: %s", value.c_str());
+      }
+      config->SetMaxExecutionSeconds(seconds);
+    } else if (ArgumentMatches(arg, "--max-child-process-seconds=", &value)) {
+      int seconds;
+      if (!android::base::ParseInt(value, &seconds)) {
+        ArgumentError("Failed to parse integer: %s", value.c_str());
+      }
+      config->SetMaxChildProcessSeconds(seconds);
     } else if (!InitializeCommonConfig(arg, config)) {
       UsageError("Unrecognized argument: '%s'", arg);
     }