odrefresh: Check build-time userfaultfd GC flag.

This is a safety net to fix artifacts if build-time right userfaultfd GC
flag doesn't match the runtime one.

Bug: 242553398
Test: -
  1. Build a system image with `m`.
  2. Flash to a device.
  3. See odrefresh not compiling anything on the first boot.
Test: -
  1. Build a system image with `OVERRIDE_ENABLE_UFFD_GC=true m`
  2. Flash to a device.
  3. See odrefresh compiling everything on the first boot (because
     aosp/2308662 has not landed yet).
Change-Id: If8cddabc8beac588ca1e75d01ee3846a2bbf56c8
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index aec9636..1ac65e6 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -56,6 +56,7 @@
 #include "android-base/file.h"
 #include "android-base/logging.h"
 #include "android-base/macros.h"
+#include "android-base/parsebool.h"
 #include "android-base/parseint.h"
 #include "android-base/properties.h"
 #include "android-base/result.h"
@@ -76,6 +77,7 @@
 #include "dex/art_dex_file_loader.h"
 #include "dexoptanalyzer.h"
 #include "exec_utils.h"
+#include "fmt/format.h"
 #include "log/log.h"
 #include "odr_artifacts.h"
 #include "odr_common.h"
@@ -86,16 +88,21 @@
 #include "odrefresh/odrefresh.h"
 #include "palette/palette.h"
 #include "palette/palette_types.h"
+#include "read_barrier_config.h"
 
 namespace art {
 namespace odrefresh {
 
+namespace {
+
 namespace apex = com::android::apex;
 namespace art_apex = com::android::art;
 
-using android::base::Result;
+using ::android::base::ParseBool;
+using ::android::base::ParseBoolResult;
+using ::android::base::Result;
 
-namespace {
+using ::fmt::literals::operator""_format;  // NOLINT
 
 // Name of cache info file in the ART Apex artifact cache.
 constexpr const char* kCacheInfoFile = "cache-info.xml";
@@ -905,17 +912,35 @@
   return true;
 }
 
+WARN_UNUSED bool OnDeviceRefresh::CheckBuildUserfaultFdGc() const {
+  auto it = config_.GetSystemProperties().find("ro.dalvik.vm.enable_uffd_gc");
+  bool build_enable_uffd_gc = it != config_.GetSystemProperties().end() ?
+                                  ParseBool(it->second) == ParseBoolResult::kTrue :
+                                  false;
+  if (build_enable_uffd_gc != gUseUserfaultfd) {
+    // Normally, this should not happen. If this happens, the system image was probably built with a
+    // wrong PRODUCT_ENABLE_UFFD_GC flag.
+    LOG(WARNING) << "Userfaultfd GC check failed (build-time: {}, runtime: {})."_format(
+        build_enable_uffd_gc, gUseUserfaultfd);
+    return false;
+  }
+  return true;
+}
+
 WARN_UNUSED bool OnDeviceRefresh::BootClasspathArtifactsOnSystemUsable(
     const apex::ApexInfo& art_apex_info) const {
   if (!art_apex_info.getIsFactory()) {
+    LOG(INFO) << "Updated ART APEX mounted";
     return false;
   }
-  LOG(INFO) << "Factory ART APEX mounted.";
 
   if (!CheckSystemPropertiesAreDefault()) {
     return false;
   }
-  LOG(INFO) << "System properties are set to default values.";
+
+  if (!CheckBuildUserfaultFdGc()) {
+    return false;
+  }
 
   return true;
 }
@@ -925,14 +950,17 @@
   if (std::any_of(apex_info_list.begin(),
                   apex_info_list.end(),
                   [](const apex::ApexInfo& apex_info) { return !apex_info.getIsFactory(); })) {
+    LOG(INFO) << "Updated APEXes mounted";
     return false;
   }
-  LOG(INFO) << "Factory APEXes mounted.";
 
   if (!CheckSystemPropertiesAreDefault()) {
     return false;
   }
-  LOG(INFO) << "System properties are set to default values.";
+
+  if (!CheckBuildUserfaultFdGc()) {
+    return false;
+  }
 
   return true;
 }
diff --git a/odrefresh/odrefresh.h b/odrefresh/odrefresh.h
index b14aa41..ff3d660 100644
--- a/odrefresh/odrefresh.h
+++ b/odrefresh/odrefresh.h
@@ -150,6 +150,9 @@
   WARN_UNUSED bool CheckSystemPropertiesHaveNotChanged(
       const com::android::art::CacheInfo& cache_info) const;
 
+  // Returns true if the system image is built with the right userfaultfd GC flag.
+  WARN_UNUSED bool CheckBuildUserfaultFdGc() const;
+
   // Returns true if boot classpath artifacts on /system are usable if they exist. Note that this
   // function does not check file existence.
   WARN_UNUSED bool BootClasspathArtifactsOnSystemUsable(