Support per-partition timestamps

update_engine is heading toward supporting partial updates, which an OTA
update can update just a subset of all partitions. In this context, a
single max_timestamp in OTA manifest is insufficient for checking
potential downgrades, as different partitions can have different
timestamps. This CL adds per-partition timestamp support on
update_engine side. update_engine will accept a payload with
per-partition timestamps and reject the update if any partition has an
older timestamp.

Changes made:
  1. Add new version field to PartitionUpdate protobuf message.
  2. Add new methods to HardwareInterface for fetching/checking
  timestamp of each partition.
  3. Update delta_performer to invoke new APIs in 2 properly.
  4. Add relevant testcases.

Test: unittest
Bug: 162553432
Change-Id: I767343e003fd35ce0d22197b15040488cf30be30
diff --git a/hardware_android.cc b/hardware_android.cc
index 0bf05e4..659e67e 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -19,13 +19,17 @@
 #include <sys/types.h>
 
 #include <memory>
+#include <string>
+#include <string_view>
 
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <base/files/file_util.h>
 #include <bootloader_message/bootloader_message.h>
 
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/platform_constants.h"
+#include "update_engine/common/utils.h"
 
 using android::base::GetBoolProperty;
 using android::base::GetIntProperty;
@@ -223,4 +227,24 @@
   }
 }
 
+std::string HardwareAndroid::GetVersionForLogging(
+    const std::string& partition_name) const {
+  return android::base::GetProperty("ro." + partition_name + ".build.date.utc",
+                                    "");
+}
+
+bool HardwareAndroid::IsPartitionUpdateValid(
+    const std::string& partition_name, const std::string& new_version) const {
+  const auto old_version = GetVersionForLogging(partition_name);
+  // TODO(zhangkelvin)  for some partitions, missing a current timestamp should
+  // be an error, e.g. system, vendor, product etc.
+  auto applicable = utils::IsTimestampNewer(old_version, new_version);
+  if (!applicable) {
+    LOG(ERROR) << "Timestamp on partition " << partition_name
+               << " is newer than update. Partition timestamp: " << old_version
+               << " Update timestamp: " << new_version;
+  }
+  return applicable;
+}
+
 }  // namespace chromeos_update_engine