Make checkpointing atomic

Update Engine currently has a bug where if it the process is interrupted
during checkpointing, we are unable to resume progress from where we
were previously. This is because prefs are reset at the beginning of
checkpointing and then slowly updated during checkpointing, if
update_engine is interrupted during this stage, it loses its state. This
change allows us to update the prefs non-destructively and then
atomically replace the old prefs with the new ones.

Test: m update_engine. update_device.py tested resume ota
Change-Id: I3a7edf7498be9cde5c6f34e3cb259a7853f4f443
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 3b9f2b6..3bd131d 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -1404,9 +1404,12 @@
     return false;
   }
   Terminator::set_exit_blocked(true);
+  LOG_IF(WARNING, !prefs_->StartTransaction())
+      << "unable to start transaction in checkpointing";
+  DEFER {
+    prefs_->CancelTransaction();
+  };
   if (last_updated_operation_num_ != next_operation_num_ || force) {
-    // Resets the progress in case we die in the middle of the state update.
-    ResetUpdateProgress(prefs_, true);
     if (!signatures_message_data_.empty()) {
       // Save the signature blob because if the update is interrupted after the
       // download phase we don't go through this path anymore. Some alternatives
@@ -1458,6 +1461,9 @@
   }
   TEST_AND_RETURN_FALSE(
       prefs_->SetInt64(kPrefsUpdateStateNextOperation, next_operation_num_));
+  if (!prefs_->SubmitTransaction()) {
+    LOG(ERROR) << "Failed to submit transaction in checkpointing";
+  }
   return true;
 }