Enable UFFD GC by default for Android U and above.

Bug: 251150519
Test: atest art_standalone_odrefresh_tests
Test: (Tested on main) -
  1. Build with OVERRIDE_ENABLE_UFFD_GC=false
  2. See odrefresh triggered on the first boot.
  3. See "Using CollectorTypeCMC GC".
Test: (Tested on UDC) -
  1. Build and install the ART APEX.
  2. See odrefresh triggered on the reboot.
  3. See "Using CollectorTypeCMC GC".
Change-Id: I212f08fa4d51b4cdac3baedd922df815cd270581
diff --git a/odrefresh/odr_common.cc b/odrefresh/odr_common.cc
index d76aff2..d7cc4d1 100644
--- a/odrefresh/odr_common.cc
+++ b/odrefresh/odr_common.cc
@@ -88,5 +88,12 @@
       &action);
 }
 
+bool CheckBuildUserfaultFdGc(bool build_enable_uffd_gc,
+                             bool is_at_least_u,
+                             bool kernel_supports_uffd) {
+  bool runtime_uses_uffd_gc = (build_enable_uffd_gc || is_at_least_u) && kernel_supports_uffd;
+  return build_enable_uffd_gc == runtime_uses_uffd_gc;
+}
+
 }  // namespace odrefresh
 }  // namespace art
diff --git a/odrefresh/odr_common.h b/odrefresh/odr_common.h
index e55258f..79babd2 100644
--- a/odrefresh/odr_common.h
+++ b/odrefresh/odr_common.h
@@ -44,6 +44,11 @@
 // Passes the name and the value for each system property to the provided callback.
 void SystemPropertyForeach(std::function<void(const char* name, const char* value)> action);
 
+// Returns true if the build-time UFFD GC matches the runtime's choice.
+bool CheckBuildUserfaultFdGc(bool build_enable_uffd_gc,
+                             bool is_at_least_u,
+                             bool kernel_supports_uffd);
+
 }  // namespace odrefresh
 }  // namespace art
 
diff --git a/odrefresh/odr_common_test.cc b/odrefresh/odr_common_test.cc
index 150f57b..63fcfd6 100644
--- a/odrefresh/odr_common_test.cc
+++ b/odrefresh/odr_common_test.cc
@@ -55,5 +55,24 @@
   EXPECT_FALSE(ShouldDisableRefresh("invalid"));
 }
 
+TEST(OdrCommonTest, CheckBuildUserfaultFdGc) {
+  EXPECT_TRUE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/false, /*is_at_least_u=*/false, /*kernel_supports_uffd=*/false));
+  EXPECT_FALSE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/true, /*is_at_least_u=*/false, /*kernel_supports_uffd=*/false));
+  EXPECT_TRUE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/false, /*is_at_least_u=*/true, /*kernel_supports_uffd=*/false));
+  EXPECT_FALSE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/true, /*is_at_least_u=*/true, /*kernel_supports_uffd=*/false));
+  EXPECT_TRUE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/false, /*is_at_least_u=*/false, /*kernel_supports_uffd=*/true));
+  EXPECT_TRUE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/true, /*is_at_least_u=*/false, /*kernel_supports_uffd=*/true));
+  EXPECT_FALSE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/false, /*is_at_least_u=*/true, /*kernel_supports_uffd=*/true));
+  EXPECT_TRUE(CheckBuildUserfaultFdGc(
+      /*build_enable_uffd_gc=*/true, /*is_at_least_u=*/true, /*kernel_supports_uffd=*/true));
+}
+
 }  // namespace odrefresh
 }  // namespace art
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index a99efc2..a6bddb3 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -1086,13 +1086,18 @@
 WARN_UNUSED bool OnDeviceRefresh::CheckBuildUserfaultFdGc() const {
   bool build_enable_uffd_gc =
       config_.GetSystemProperties().GetBool("ro.dalvik.vm.enable_uffd_gc", /*default_value=*/false);
+  bool is_at_least_u = IsAtLeastU();
   bool kernel_supports_uffd = KernelSupportsUffd();
-  if (build_enable_uffd_gc && !kernel_supports_uffd) {
+  if (!art::odrefresh::CheckBuildUserfaultFdGc(
+          build_enable_uffd_gc, is_at_least_u, kernel_supports_uffd)) {
     // Normally, this should not happen. If this happens, the system image was probably built with a
     // wrong PRODUCT_ENABLE_UFFD_GC flag.
-    LOG(WARNING) << ART_FORMAT("Userfaultfd GC check failed (build-time: {}, runtime: {}).",
-                               build_enable_uffd_gc,
-                               kernel_supports_uffd);
+    LOG(WARNING) << ART_FORMAT(
+        "Userfaultfd GC check failed (build_enable_uffd_gc: {}, is_at_least_u: {}, "
+        "kernel_supports_uffd: {}).",
+        build_enable_uffd_gc,
+        is_at_least_u,
+        kernel_supports_uffd);
     return false;
   }
   return true;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 9b67dd9..f7568be 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -436,6 +436,7 @@
                 "heapprofd_client_api",
             ],
             static_libs: [
+                "libmodules-utils-build",
                 "libstatslog_art",
             ],
             generated_sources: [
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index ad308f4..74c8174 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -58,6 +58,7 @@
 #include "thread_list.h"
 
 #ifdef ART_TARGET_ANDROID
+#include "android-modules-utils/sdk_level.h"
 #include "com_android_art.h"
 #endif
 
@@ -89,6 +90,7 @@
 using ::android::base::GetBoolProperty;
 using ::android::base::ParseBool;
 using ::android::base::ParseBoolResult;
+using ::android::modules::sdklevel::IsAtLeastU;
 
 }  // namespace
 #endif
@@ -261,7 +263,7 @@
   bool phenotype_force_disable = GetCachedBoolProperty(
       cached_properties, "persist.device_config.runtime_native_boot.force_disable_uffd_gc", false);
   bool build_enable = GetBoolProperty("ro.dalvik.vm.enable_uffd_gc", false);
-  return (phenotype_enable || build_enable) && !phenotype_force_disable;
+  return (phenotype_enable || build_enable || IsAtLeastU()) && !phenotype_force_disable;
 }
 #else
 // Never called.