Defer marking boot successful when checkpointing

This moves actually marking the slot as successful to a later point
so that on devices with checkpointing enabled we can still roll back to
the previous version if we fail to boot to the point that the checkpoint
is marked as successful.

Test: When taking an update on a checkpoint enabled device, it
      defers marking the slot as successful instead of directly
      marking it. Visible in logs.
Bug: 123260515

Change-Id: I7ed3595c1b0904ddbfe20d1cad4f69ecbf1ea351
diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp
index 1b84619..f656713 100644
--- a/update_verifier/Android.bp
+++ b/update_verifier/Android.bp
@@ -42,12 +42,15 @@
 
     static_libs: [
         "libotautil",
+        "libvold_binder",
     ],
 
     shared_libs: [
         "android.hardware.boot@1.0",
         "libbase",
         "libcutils",
+        "libbinder",
+        "libutils",
     ],
 
     proto: {
@@ -70,6 +73,7 @@
     static_libs: [
         "libupdate_verifier",
         "libotautil",
+        "libvold_binder",
     ],
 
     shared_libs: [
@@ -80,6 +84,7 @@
         "libhidlbase",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libbinder",
         "libutils",
     ],
 
diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
index d7cd061..5e5eac7 100644
--- a/update_verifier/update_verifier.cpp
+++ b/update_verifier/update_verifier.cpp
@@ -38,6 +38,7 @@
  */
 
 #include "update_verifier/update_verifier.h"
+#include <android/os/IVold.h>
 
 #include <dirent.h>
 #include <errno.h>
@@ -56,6 +57,8 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
+#include <binder/BinderService.h>
+#include <binder/Status.h>
 #include <cutils/android_reboot.h>
 
 #include "care_map.pb.h"
@@ -376,13 +379,30 @@
       }
     }
 
-    CommandResult cr;
-    module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
-    if (!cr.success) {
-      LOG(ERROR) << "Error marking booted successfully: " << cr.errMsg;
-      return reboot_device();
+    bool supports_checkpoint = false;
+    auto sm = android::defaultServiceManager();
+    android::sp<android::IBinder> binder = sm->getService(android::String16("vold"));
+    if (binder) {
+      auto vold = android::interface_cast<android::os::IVold>(binder);
+      android::binder::Status status = vold->supportsCheckpoint(&supports_checkpoint);
+      if (!status.isOk()) {
+        LOG(ERROR) << "Failed to check if checkpoints supported. Continuing";
+      }
+    } else {
+      LOG(ERROR) << "Failed to obtain vold Binder. Continuing";
     }
-    LOG(INFO) << "Marked slot " << current_slot << " as booted successfully.";
+
+    if (!supports_checkpoint) {
+      CommandResult cr;
+      module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
+      if (!cr.success) {
+        LOG(ERROR) << "Error marking booted successfully: " << cr.errMsg;
+        return reboot_device();
+      }
+      LOG(INFO) << "Marked slot " << current_slot << " as booted successfully.";
+    } else {
+      LOG(INFO) << "Deferred marking slot " << current_slot << " as booted successfully.";
+    }
   }
 
   LOG(INFO) << "Leaving update_verifier.";