Send an UMA metric when failed to boot into the new partition.

When a payload is successfully applied, the /other/ partition
is marked as valid and a reboot is needed, the reboot into this
new partition can fail due to several reasons. If than happens,
the firmware can rollback to the previous partition.

When this happens, this fix sends a new UMA metric with the
attempt number of this failing payload.

In order to test this functionality we need to fake the
utils::BootDevice() to emulate a reboot into the same or
a different partition. To achieve this, this function is
moved to a new "HardwareInterface" that can be faked
using the FakeHardware class that can hold similar hardware
related functions. Implementations and unittest were
refactored as needed.

BUG=chromium:243572
TEST=unittests

Change-Id: I1a4242df0bd61e2718ab881ead603b1d3705b877
Reviewed-on: https://gerrit.chromium.org/gerrit/61815
Commit-Queue: Alex Deymo <deymo@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/payload_state.h b/payload_state.h
index 8c3133c..64d134f 100644
--- a/payload_state.h
+++ b/payload_state.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_H__
 
 #include <base/time.h>
+#include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
 #include "update_engine/payload_state_interface.h"
 #include "update_engine/prefs_interface.h"
@@ -39,8 +40,10 @@
   virtual void UpdateRestarted();
   virtual void UpdateSucceeded();
   virtual void UpdateFailed(ErrorCode error);
+  virtual void ResetUpdateStatus();
   virtual bool ShouldBackoffDownload();
   virtual void Rollback();
+  virtual void ExpectRebootInNewVersion(const std::string& target_version_uid);
 
   virtual inline std::string GetResponseSignature() {
     return response_signature_;
@@ -97,6 +100,12 @@
   }
 
  private:
+  friend class PayloadStateTest;
+  FRIEND_TEST(PayloadStateTest, RebootAfterUpdateFailedMetric);
+  FRIEND_TEST(PayloadStateTest, RebootAfterUpdateSucceed);
+  FRIEND_TEST(PayloadStateTest, RebootAfterCanceledUpdate);
+  FRIEND_TEST(PayloadStateTest, UpdateSuccessWithWipedPrefs);
+
   // Increments the payload attempt number used for metrics.
   void IncrementPayloadAttemptNumber();
 
@@ -147,6 +156,13 @@
   // Reports the various metrics related to update attempts counts.
   void ReportAttemptsCountMetrics();
 
+  // Checks if we were expecting to be running in the new version but the
+  // boot into the new version failed for some reason. If that's the case, an
+  // UMA metric is sent reporting the number of attempts the same applied
+  // payload was attempted to reboot. This function is called by UpdateAttempter
+  // every time the update engine starts and there's no reboot pending.
+  void ReportFailedBootIfNeeded();
+
   // Resets all the persisted state values which are maintained relative to the
   // current response signature. The response signature itself is not reset.
   void ResetPersistedState();