Read boot image version from ro.bootimage.build.date.utc

This change re-defines boot image downgrade check logic. The
sysprop ro.bootimage.build.date.utc is checked instead. If the
sysprop ro.build.ab_update.gki.prevent_downgrade_version is not set,
any detected downgrades are suppressed.

Bug: 162554855
Bug: 162623577
Bug: 169169031
Test: pass

Change-Id: Ib86cb40576a852e0654a4c22d81c876d0315d0d2
diff --git a/hardware_android.cc b/hardware_android.cc
index fc6e1dc..a659bf6 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -17,7 +17,6 @@
 #include "update_engine/hardware_android.h"
 
 #include <sys/types.h>
-#include <sys/utsname.h>
 
 #include <memory>
 #include <string>
@@ -28,8 +27,6 @@
 #include <android-base/properties.h>
 #include <base/files/file_util.h>
 #include <bootloader_message/bootloader_message.h>
-#include <kver/kernel_release.h>
-#include <kver/utils.h>
 
 #include "update_engine/common/error_code_utils.h"
 #include "update_engine/common/hardware.h"
@@ -39,8 +36,6 @@
 using android::base::GetBoolProperty;
 using android::base::GetIntProperty;
 using android::base::GetProperty;
-using android::kver::IsKernelUpdateValid;
-using android::kver::KernelRelease;
 using std::string;
 
 namespace chromeos_update_engine {
@@ -62,6 +57,19 @@
                                     "");
 }
 
+ErrorCode IsTimestampNewerLogged(const std::string& partition_name,
+                                 const std::string& old_version,
+                                 const std::string& new_version) {
+  auto error_code = utils::IsTimestampNewer(old_version, new_version);
+  if (error_code != ErrorCode::kSuccess) {
+    LOG(WARNING) << "Timestamp check failed with "
+                 << utils::ErrorCodeToString(error_code) << ": "
+                 << partition_name << " Partition timestamp: " << old_version
+                 << " Update timestamp: " << new_version;
+  }
+  return error_code;
+}
+
 }  // namespace
 
 namespace hardware {
@@ -242,14 +250,8 @@
 string HardwareAndroid::GetVersionForLogging(
     const string& partition_name) const {
   if (partition_name == "boot") {
-    struct utsname buf;
-    if (uname(&buf) != 0) {
-      PLOG(ERROR) << "Unable to call uname()";
-      return "";
-    }
-    auto kernel_release =
-        KernelRelease::Parse(buf.release, true /* allow_suffix */);
-    return kernel_release.has_value() ? kernel_release->string() : "";
+    // ro.bootimage.build.date.utc
+    return GetPartitionBuildDate("bootimage");
   }
   return GetPartitionBuildDate(partition_name);
 }
@@ -257,61 +259,33 @@
 ErrorCode HardwareAndroid::IsPartitionUpdateValid(
     const string& partition_name, const string& new_version) const {
   if (partition_name == "boot") {
-    struct utsname buf;
-    if (uname(&buf) != 0) {
-      PLOG(ERROR) << "Unable to call uname()";
-      return ErrorCode::kError;
+    const auto old_version = GetPartitionBuildDate("bootimage");
+    auto error_code =
+        IsTimestampNewerLogged(partition_name, old_version, new_version);
+    if (error_code == ErrorCode::kPayloadTimestampError) {
+      bool prevent_downgrade =
+          android::sysprop::GkiProperties::prevent_downgrade_version().value_or(
+              false);
+      if (!prevent_downgrade) {
+        LOG(WARNING) << "Downgrade of boot image is detected, but permitting "
+                        "update because device does not prevent boot image "
+                        "downgrade";
+        // If prevent_downgrade_version sysprop is not explicitly set, permit
+        // downgrade in boot image version.
+        // Even though error_code is overridden here, always call
+        // IsTimestampNewerLogged to produce log messages.
+        error_code = ErrorCode::kSuccess;
+      }
     }
-    bool prevent_downgrade =
-        android::sysprop::GkiProperties::prevent_downgrade_version().value_or(
-            false);
-    return IsKernelUpdateValid(buf.release, new_version, prevent_downgrade);
+    return error_code;
   }
 
   const auto old_version = GetPartitionBuildDate(partition_name);
   // TODO(zhangkelvin)  for some partitions, missing a current timestamp should
   // be an error, e.g. system, vendor, product etc.
-  auto error_code = utils::IsTimestampNewer(old_version, new_version);
-  if (error_code != ErrorCode::kSuccess) {
-    LOG(ERROR) << "Timestamp check failed with "
-               << utils::ErrorCodeToString(error_code)
-               << " Partition timestamp: " << old_version
-               << " Update timestamp: " << new_version;
-  }
+  auto error_code =
+      IsTimestampNewerLogged(partition_name, old_version, new_version);
   return error_code;
 }
 
-ErrorCode HardwareAndroid::IsKernelUpdateValid(const string& old_release,
-                                               const string& new_release,
-                                               bool prevent_downgrade) {
-  // Check that the package either contain an empty version (indicating that the
-  // new build does not use GKI), or a valid GKI kernel release.
-  std::optional<KernelRelease> new_kernel_release;
-  if (new_release.empty()) {
-    LOG(INFO) << "New build does not contain GKI.";
-  } else {
-    new_kernel_release =
-        KernelRelease::Parse(new_release, true /* allow_suffix */);
-    if (!new_kernel_release.has_value()) {
-      LOG(ERROR) << "New kernel release is not valid GKI kernel release: "
-                 << new_release;
-      return ErrorCode::kDownloadManifestParseError;
-    }
-  }
-
-  auto old_kernel_release =
-      KernelRelease::Parse(old_release, true /* allow_suffix */);
-  bool is_update_valid = android::kver::IsKernelUpdateValid(old_kernel_release,
-                                                            new_kernel_release);
-
-  if (!is_update_valid) {
-    if (prevent_downgrade) {
-      return ErrorCode::kPayloadTimestampError;
-    }
-    LOG(WARNING) << "Boot version downgrade detected, allowing update because "
-                 << "prevent_downgrade_version sysprop is not set.";
-  }
-  return ErrorCode::kSuccess;
-}
-
 }  // namespace chromeos_update_engine