vold: implement resetCheckpoint

It will be used by userspace reboot to reset checkpoint state, to make
sure that when /data is remounted, it will be remounted in checkpointing
if a checkpoint was requested beforee userspace reboot.

Test: /system/bin/vdc startCheckpoint 1
      /system/bin/vdc needsCheckpoint (returns 0)
      /system/bin/vdc resetCheckpoint
      /system/bin/vdc needsCheckpoint (returns 1)

Bug: 135984674
Change-Id: Ia29238686289b4eed93e2fb936a8b3d894b94dc9
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index e5ef4a2..a4e8fc8 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -145,8 +145,10 @@
 
 volatile bool isCheckpointing = false;
 
-// Protects isCheckpointing and code that makes decisions based on status of
-// isCheckpointing
+volatile bool needsCheckpointWasCalled = false;
+
+// Protects isCheckpointing, needsCheckpointWasCalled and code that makes decisions based on status
+// of isCheckpointing
 std::mutex isCheckpointingLock;
 }
 
@@ -263,16 +265,16 @@
 }
 
 bool cp_needsCheckpoint() {
+    std::lock_guard<std::mutex> lock(isCheckpointingLock);
+
     // Make sure we only return true during boot. See b/138952436 for discussion
-    static bool called_once = false;
-    if (called_once) return isCheckpointing;
-    called_once = true;
+    if (needsCheckpointWasCalled) return isCheckpointing;
+    needsCheckpointWasCalled = true;
 
     bool ret;
     std::string content;
     sp<IBootControl> module = IBootControl::getService();
 
-    std::lock_guard<std::mutex> lock(isCheckpointingLock);
     if (isCheckpointing) return isCheckpointing;
 
     if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
@@ -727,5 +729,10 @@
     return Status::ok();
 }
 
+void cp_resetCheckpoint() {
+    std::lock_guard<std::mutex> lock(isCheckpointingLock);
+    needsCheckpointWasCalled = false;
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/Checkpoint.h b/Checkpoint.h
index 63ead83..c1fb2b7 100644
--- a/Checkpoint.h
+++ b/Checkpoint.h
@@ -45,6 +45,7 @@
 
 android::binder::Status cp_markBootAttempt();
 
+void cp_resetCheckpoint();
 }  // namespace vold
 }  // namespace android
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 7f7f289..0afbab9 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -907,5 +907,13 @@
     return cp_supportsFileCheckpoint(*_aidl_return);
 }
 
+binder::Status VoldNativeService::resetCheckpoint() {
+    ENFORCE_UID(AID_SYSTEM);
+    ACQUIRE_LOCK;
+
+    cp_resetCheckpoint();
+    return ok();
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 07a0b9f..13137c5 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -140,6 +140,7 @@
     binder::Status supportsCheckpoint(bool* _aidl_return);
     binder::Status supportsBlockCheckpoint(bool* _aidl_return);
     binder::Status supportsFileCheckpoint(bool* _aidl_return);
+    binder::Status resetCheckpoint();
 };
 
 }  // namespace vold
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 03fe258..8e5c53d 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -116,6 +116,7 @@
     boolean supportsCheckpoint();
     boolean supportsBlockCheckpoint();
     boolean supportsFileCheckpoint();
+    void resetCheckpoint();
 
     @utf8InCpp String createStubVolume(@utf8InCpp String sourcePath,
             @utf8InCpp String mountPath, @utf8InCpp String fsType,
diff --git a/vdc.cpp b/vdc.cpp
index 839e70e..c1b7781 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -147,6 +147,8 @@
         int retry;
         if (!android::base::ParseInt(args[2], &retry)) exit(EINVAL);
         checkStatus(args, vold->abortChanges(args[2], retry != 0));
+    } else if (args[0] == "checkpoint" && args[1] == "resetCheckpoint") {
+        checkStatus(args, vold->resetCheckpoint());
     } else {
         LOG(ERROR) << "Raw commands are no longer supported";
         exit(EINVAL);