Reject SPL downgrade for locked bootlaoders

Test: th
Bug: 270459308
Change-Id: I46ce6c59afed28377fa1513f9eb7e098755cde40
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index d5d5263..0ec6a38 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -29,6 +29,7 @@
 #include <vector>
 
 #include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <base/files/file_util.h>
 #include <base/format_macros.h>
 #include <base/metrics/histogram_macros.h>
@@ -395,27 +396,43 @@
       base::TimeDelta::FromMinutes(5),                                      \
       20);
 
-void DeltaPerformer::CheckSPLDowngrade() {
+bool DeltaPerformer::CheckSPLDowngrade() {
   if (!manifest_.has_security_patch_level()) {
-    return;
+    return true;
   }
   if (manifest_.security_patch_level().empty()) {
-    return;
+    return true;
   }
   const auto new_spl = manifest_.security_patch_level();
   const auto current_spl =
       android::base::GetProperty("ro.build.version.security_patch", "");
   if (current_spl.empty()) {
-    LOG(ERROR) << "Failed to get ro.build.version.security_patch, unable to "
-                  "determine if this OTA is a SPL downgrade.";
-    return;
+    LOG(WARNING) << "Failed to get ro.build.version.security_patch, unable to "
+                    "determine if this OTA is a SPL downgrade. Assuming this "
+                    "OTA is not SPL downgrade.";
+    return true;
   }
   if (new_spl < current_spl) {
+    const auto avb_state =
+        android::base::GetProperty("ro.boot.verifiedbootstate", "green");
+    if (android::base::EqualsIgnoreCase(avb_state, "green")) {
+      LOG(ERROR) << "Target build SPL " << new_spl
+                 << " is older than current build's SPL " << current_spl
+                 << ", this OTA is an SPL downgrade. Your device's "
+                    "ro.boot.verifiedbootstate="
+                 << avb_state
+                 << ", it probably has a locked bootlaoder. Since a locked "
+                    "bootloader will reject SPL downgrade no matter what, we "
+                    "will reject this OTA.";
+      return false;
+    }
     install_plan_->powerwash_required = true;
-    LOG(INFO) << "Target build SPL " << new_spl
-              << " is older than current build's SPL " << current_spl
-              << ", this OTA is an SPL downgrade. Data wipe will be required";
+    LOG(WARNING)
+        << "Target build SPL " << new_spl
+        << " is older than current build's SPL " << current_spl
+        << ", this OTA is an SPL downgrade. Data wipe will be required";
   }
+  return true;
 }
 
 // Wrapper around write. Returns true if all requested bytes
@@ -464,7 +481,10 @@
 
     block_size_ = manifest_.block_size();
 
-    CheckSPLDowngrade();
+    if (!CheckSPLDowngrade()) {
+      *error = ErrorCode::kPayloadTimestampError;
+      return false;
+    }
 
     // update estimate_cow_size if VABC is disabled
     // new_cow_size per partition = partition_size - (#blocks in Copy
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 7365519..12238a7 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -311,7 +311,7 @@
   // Check if partition `part_name` is a dynamic partition.
   bool IsDynamicPartition(const std::string& part_name, uint32_t slot);
 
-  void CheckSPLDowngrade();
+  bool CheckSPLDowngrade();
 
   // Update Engine preference store.
   PrefsInterface* prefs_;