recovery: allow A/B updater to downgrade
Change-Id: Iaa1fb7838fb958e69fb3104fef7743aafad12b1b
diff --git a/install/install.cpp b/install/install.cpp
index d376433..80e5f1b 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -138,7 +138,8 @@
// Checks the build version, fingerprint and timestamp in the metadata of the A/B package.
// Downgrading is not allowed unless explicitly enabled in the package and only for
// incremental packages.
-static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata) {
+static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata,
+ bool allow_ab_downgrade) {
// Incremental updates should match the current build.
auto device_pre_build = android::base::GetProperty("ro.build.version.incremental", "");
auto pkg_pre_build = get_value(metadata, "pre-build-incremental");
@@ -157,32 +158,35 @@
}
// Check for downgrade version.
- int64_t build_timestamp =
- android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max());
- int64_t pkg_post_timestamp = 0;
- // We allow to full update to the same version we are running, in case there
- // is a problem with the current copy of that version.
- auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp");
- if (pkg_post_timestamp_string.empty() ||
- !android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) ||
- pkg_post_timestamp < build_timestamp) {
- if (get_value(metadata, "ota-downgrade") != "yes") {
- LOG(ERROR) << "Update package is older than the current build, expected a build "
- "newer than timestamp "
- << build_timestamp << " but package has timestamp " << pkg_post_timestamp
- << " and downgrade not allowed.";
- return INSTALL_ERROR;
- }
- if (pkg_pre_build_fingerprint.empty()) {
- LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed.";
- return INSTALL_ERROR;
+ if (!allow_ab_downgrade) {
+ int64_t build_timestamp =
+ android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max());
+ int64_t pkg_post_timestamp = 0;
+ // We allow to full update to the same version we are running, in case there
+ // is a problem with the current copy of that version.
+ auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp");
+ if (pkg_post_timestamp_string.empty() ||
+ !android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) ||
+ pkg_post_timestamp < build_timestamp) {
+ if (get_value(metadata, "ota-downgrade") != "yes") {
+ LOG(ERROR) << "Update package is older than the current build, expected a build "
+ "newer than timestamp "
+ << build_timestamp << " but package has timestamp " << pkg_post_timestamp
+ << " and downgrade not allowed.";
+ return INSTALL_DOWNGRADE;
+ }
+ if (pkg_pre_build_fingerprint.empty()) {
+ LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed.";
+ return INSTALL_DOWNGRADE;
+ }
}
}
return 0;
}
-int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type) {
+int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type,
+ bool allow_ab_downgrade) {
auto device = android::base::GetProperty("ro.product.device", "");
auto pkg_device = get_value(metadata, "pre-device");
if (pkg_device != device || pkg_device.empty()) {
@@ -209,7 +213,7 @@
}
if (ota_type == OtaType::AB) {
- return CheckAbSpecificMetadata(metadata);
+ return CheckAbSpecificMetadata(metadata, allow_ab_downgrade);
}
return 0;
@@ -313,14 +317,14 @@
// If the package contains an update binary, extract it and run it.
static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
std::vector<std::string>* log_buffer, int retry_count,
- int* max_temperature, RecoveryUI* ui) {
+ bool allow_ab_downgrade, int* max_temperature, RecoveryUI* ui) {
std::map<std::string, std::string> metadata;
bool is_ab_ota = false;
if (ReadMetadataFromPackage(zip, &metadata)) {
ReadSourceTargetBuild(metadata, log_buffer);
if (get_value(metadata, "ota-type") == OtaTypeToString(OtaType::AB)) {
is_ab_ota = true;
- int check_status = CheckPackageMetadata(metadata, OtaType::AB);
+ int check_status = CheckPackageMetadata(metadata, OtaType::AB, allow_ab_downgrade);
if (check_status != 0) {
return check_status;
}
@@ -556,7 +560,7 @@
static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
std::vector<std::string>* log_buffer, int retry_count,
- bool verify, int* max_temperature, RecoveryUI* ui) {
+ bool verify, bool allow_ab_downgrade, int* max_temperature, RecoveryUI* ui) {
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
ui->Print("Finding update package...\n");
// Give verification half the progress bar...
@@ -607,8 +611,8 @@
ui->Print("Retry attempt: %d\n", retry_count);
}
ui->SetEnableReboot(false);
- int result =
- try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui);
+ int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, allow_ab_downgrade,
+ max_temperature, ui);
ui->SetEnableReboot(true);
ui->Print("\n");
@@ -616,7 +620,7 @@
}
int install_package(const std::string& path, bool should_wipe_cache, bool needs_mount,
- int retry_count, bool verify, RecoveryUI* ui) {
+ int retry_count, bool verify, bool allow_ab_downgrade, RecoveryUI* ui) {
CHECK(!path.empty());
auto start = std::chrono::system_clock::now();
@@ -632,7 +636,7 @@
} else {
bool updater_wipe_cache = false;
result = really_install_package(path, &updater_wipe_cache, needs_mount, &log_buffer,
- retry_count, verify, &max_temperature, ui);
+ retry_count, verify, allow_ab_downgrade, &max_temperature, ui);
should_wipe_cache = should_wipe_cache || updater_wipe_cache;
}