Allow skipping timestamp check in certain debug conditions

As proposed in go/ota-downgrade, the android auto team wants to install
a full OTA with the older timestamp. We will only allow it on devices
with userdebug build, and has the property "ro.ota.allow_downgrade"
set. Data wipe is almost inevitable due to the probability of security
patch level and database rollback.

Test: set the property and install a full payload with older timestamp.
Change-Id: I897bbb19bfec820340f791abf3c6d8138995fa90
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 3e5a66e..8da5326 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -128,6 +128,8 @@
 
   int64_t GetBuildTimestamp() const override { return build_timestamp_; }
 
+  bool AllowDowngrade() const override { return false; }
+
   bool GetFirstActiveOmahaPingSent() const override {
     return first_active_omaha_ping_sent_;
   }
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index 0140588..4a64c3e 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -122,6 +122,10 @@
   // Returns the timestamp of the current OS build.
   virtual int64_t GetBuildTimestamp() const = 0;
 
+  // Returns true if the current OS build allows installing the payload with an
+  // older timestamp.
+  virtual bool AllowDowngrade() const = 0;
+
   // Returns whether the first active ping was sent to Omaha at some point, and
   // that the value is persisted across recovery (and powerwash) once set with
   // |SetFirstActiveOmahaPingSent()|.
diff --git a/hardware_android.cc b/hardware_android.cc
index 21d4659..9611ba6 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -192,6 +192,13 @@
   return GetIntProperty<int64_t>(kPropBuildDateUTC, 0);
 }
 
+// Returns true if the device runs an userdebug build, and explicitly allows OTA
+// downgrade.
+bool HardwareAndroid::AllowDowngrade() const {
+  return GetBoolProperty("ro.ota.allow_downgrade", false) &&
+         GetBoolProperty("ro.debuggable", false);
+}
+
 bool HardwareAndroid::GetFirstActiveOmahaPingSent() const {
   LOG(WARNING) << "STUB: Assuming first active omaha was never set.";
   return false;
diff --git a/hardware_android.h b/hardware_android.h
index 5b3c99d..2a8f669 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -53,6 +53,7 @@
   bool GetNonVolatileDirectory(base::FilePath* path) const override;
   bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
   int64_t GetBuildTimestamp() const override;
+  bool AllowDowngrade() const override;
   bool GetFirstActiveOmahaPingSent() const override;
   bool SetFirstActiveOmahaPingSent() override;
 
diff --git a/hardware_chromeos.h b/hardware_chromeos.h
index 8829866..57be3b0 100644
--- a/hardware_chromeos.h
+++ b/hardware_chromeos.h
@@ -58,6 +58,7 @@
   bool GetNonVolatileDirectory(base::FilePath* path) const override;
   bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
   int64_t GetBuildTimestamp() const override;
+  bool AllowDowngrade() const override { return false; }
   bool GetFirstActiveOmahaPingSent() const override;
   bool SetFirstActiveOmahaPingSent() override;
 
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 4aec00b..8b3f61c 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -1692,7 +1692,11 @@
                << hardware_->GetBuildTimestamp()
                << ") is newer than the maximum timestamp in the manifest ("
                << manifest_.max_timestamp() << ")";
-    return ErrorCode::kPayloadTimestampError;
+    if (!hardware_->AllowDowngrade()) {
+      return ErrorCode::kPayloadTimestampError;
+    }
+    LOG(INFO) << "The current OS build allows downgrade, continuing to apply"
+                 " the payload with an older timestamp.";
   }
 
   if (major_payload_version_ == kChromeOSMajorPayloadVersion) {