AU: Fall back to a new update after a certain number of failed resume attempts.

BUG=7483
TEST=unit tests, gmerged on device and inspected preferences

Change-Id: I9d184b314c359f32a9791afd8da7eb6607f428eb

Review URL: http://codereview.chromium.org/3575024
diff --git a/delta_performer.cc b/delta_performer.cc
index 9bf3d34..8fc479b 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -40,6 +40,7 @@
 const char kUpdatePayloadPublicKeyPath[] =
     "/usr/share/update_engine/update-payload-key.pub.pem";
 const int kUpdateStateOperationInvalid = -1;
+const int kMaxResumedUpdateFailures = 10;
 
 // Converts extents to a human-readable string, for use by DumpUpdateProto().
 string ExtentsToString(const RepeatedPtrField<Extent>& extents) {
@@ -563,6 +564,11 @@
                         !interrupted_hash.empty() &&
                         interrupted_hash == update_check_response_hash);
 
+  int64_t resumed_update_failures;
+  TEST_AND_RETURN_FALSE(!prefs->GetInt64(kPrefsResumedUpdateFailures,
+                                         &resumed_update_failures) ||
+                        resumed_update_failures <= kMaxResumedUpdateFailures);
+
   // Sanity check the rest.
   int64_t next_data_offset = -1;
   TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsUpdateStateNextDataOffset,
@@ -591,6 +597,7 @@
     prefs->SetString(kPrefsUpdateStateSHA256Context, "");
     prefs->SetString(kPrefsUpdateStateSignedSHA256Context, "");
     prefs->SetInt64(kPrefsManifestMetadataSize, -1);
+    prefs->SetInt64(kPrefsResumedUpdateFailures, 0);
   }
   return true;
 }
@@ -648,6 +655,14 @@
                         manifest_metadata_size > 0);
   manifest_metadata_size_ = manifest_metadata_size;
 
+  // Speculatively count the resume as a failure.
+  int64_t resumed_update_failures;
+  if (prefs_->GetInt64(kPrefsResumedUpdateFailures, &resumed_update_failures)) {
+    resumed_update_failures++;
+  } else {
+    resumed_update_failures = 1;
+  }
+  prefs_->SetInt64(kPrefsResumedUpdateFailures, resumed_update_failures);
   return true;
 }
 
diff --git a/prefs.cc b/prefs.cc
index 733443c..bdd620b 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -19,6 +19,7 @@
 const char kPrefsLastActivePingDay[] = "last-active-ping-day";
 const char kPrefsLastRollCallPingDay[] = "last-roll-call-ping-day";
 const char kPrefsManifestMetadataSize[] = "manifest-metadata-size";
+const char kPrefsResumedUpdateFailures[] = "resumed-update-failures";
 const char kPrefsUpdateCheckResponseHash[] = "update-check-response-hash";
 const char kPrefsUpdateStateNextDataOffset[] = "update-state-next-data-offset";
 const char kPrefsUpdateStateNextOperation[] = "update-state-next-operation";
diff --git a/prefs_interface.h b/prefs_interface.h
index 66fe8cb..81aa770 100644
--- a/prefs_interface.h
+++ b/prefs_interface.h
@@ -13,6 +13,7 @@
 extern const char kPrefsLastActivePingDay[];
 extern const char kPrefsLastRollCallPingDay[];
 extern const char kPrefsManifestMetadataSize[];
+extern const char kPrefsResumedUpdateFailures[];
 extern const char kPrefsUpdateCheckResponseHash[];
 extern const char kPrefsUpdateStateNextDataOffset[];
 extern const char kPrefsUpdateStateNextOperation[];