libdm: Fallback to legacy ueventd logic if running on an older system.

When delivering single-stage, non-AB OTAs, the updater binary is built
on a newer OS than recovery is compiled with. libdm relies on newer ueventd
behavior which therefore breaks this model. As a workaround, we allow
libdm to fallback to the old ueventd logic if the following conditions
hold true: (1) we're in recovery, (2) the device is not an AB device,
and (3) the release is <= 10.

Since the old ueventd behavior can lead to races in libdm, this fallback
should stay as narrow as possible.

Bug: 156536673
Bug: 155202260
Test: manual test
Change-Id: I7f9da49e4ba8dfe165e0923d9918827d51d090cd
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 673e145..7912688 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -29,6 +29,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <uuid/uuid.h>
 
@@ -140,6 +141,10 @@
     return std::string{uuid_chars};
 }
 
+static bool IsRecovery() {
+    return access("/system/bin/recovery", F_OK) == 0;
+}
+
 bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table, std::string* path,
                                 const std::chrono::milliseconds& timeout_ms) {
     std::string uuid = GenerateUuid();
@@ -160,6 +165,16 @@
     if (timeout_ms <= std::chrono::milliseconds::zero()) {
         return true;
     }
+
+    if (IsRecovery()) {
+        bool non_ab_device = android::base::GetProperty("ro.build.ab_update", "").empty();
+        int sdk = android::base::GetIntProperty("ro.build.version.sdk", 0);
+        if (non_ab_device && sdk && sdk <= 29) {
+            LOG(INFO) << "Detected ueventd incompatibility, reverting to legacy libdm behavior.";
+            unique_path = *path;
+        }
+    }
+
     if (!WaitForFile(unique_path, timeout_ms)) {
         LOG(ERROR) << "Failed waiting for device path: " << unique_path;
         DeleteDevice(name);