Fix rollback detection
After OTA finishes, update_engine writes boot id to /data/ to indicate
that a slot switch is scheduled. This is called a slot switch indicator.
After device reboots, update_engine uses value of the slot switch
indicator to determine if a slot switch was attempted for last reboot.
If slot switch was attempted but device is still on the old slot,
update_engine declares that a rollback has happened.
However, the slot switch indactor is only cleared when next OTA starts,
so if the device was rebooted during merge(or before next OTA starts),
update_engine would mistakenly think that a slot switch was attempted.
Test: reboot device during merge, make sure UE did not detect a rollback
Change-Id: Ia557cc14e4f217813fdcb7896b49131898e8bfd3
diff --git a/aosp/boot_control_android.cc b/aosp/boot_control_android.cc
index 291fc61..0a1d3de 100644
--- a/aosp/boot_control_android.cc
+++ b/aosp/boot_control_android.cc
@@ -26,7 +26,6 @@
#include <brillo/message_loops/message_loop.h>
#include "update_engine/aosp/dynamic_partition_control_android.h"
-#include "update_engine/common/utils.h"
using std::string;
diff --git a/aosp/cow_converter.cc b/aosp/cow_converter.cc
index e464605..b9ec00a 100644
--- a/aosp/cow_converter.cc
+++ b/aosp/cow_converter.cc
@@ -29,7 +29,6 @@
#include <libsnapshot/cow_writer.h>
#include <gflags/gflags.h>
-#include "update_engine/common/cow_operation_convert.h"
#include "update_engine/common/utils.h"
#include "update_engine/payload_consumer/file_descriptor.h"
#include "update_engine/payload_consumer/payload_metadata.h"
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index ea0b0d9..f9e0d11 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -820,9 +820,10 @@
}
bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
- LOG(INFO) << "Writing update complete marker.";
string boot_id;
TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
+ LOG(INFO) << "Writing update complete marker, slot "
+ << boot_control_->GetCurrentSlot() << ", boot id: " << boot_id;
TEST_AND_RETURN_FALSE(
prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id));
TEST_AND_RETURN_FALSE(
@@ -837,7 +838,7 @@
return true;
}
-bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
+bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() const {
// In case of an update_engine restart without a reboot, we stored the boot_id
// when the update was completed by setting a pref, so we can check whether
// the last update was on this boot or a previous one.
@@ -945,7 +946,9 @@
prefs_->GetString(kPrefsPreviousVersion, &previous_version));
if (previous_slot != current_slot) {
LOG(INFO) << "Detected a slot switch, OTA succeeded, device updated from "
- << previous_version << " to " << current_version;
+ << previous_version << " to " << current_version
+ << ", previous slot: " << previous_slot
+ << " current slot: " << current_slot;
if (previous_version == current_version) {
LOG(INFO) << "Previous version is the same as current version, this is "
"possibly a self-OTA.";
@@ -967,7 +970,8 @@
// We only set |kPrefsSystemUpdatedMarker| if slot is actually switched, so
// existence of this pref is sufficient indicator. Given that we have to
// delete this pref after checking it. This is done in
- // |DeltaPerformer::ResetUpdateProgress|
+ // |DeltaPerformer::ResetUpdateProgress| and
+ // |UpdateAttempterAndroid::UpdateStateAfterReboot|
auto slot_switch_attempted = prefs_->Exists(kPrefsUpdateCompletedOnBootId);
auto system_rebooted = DidSystemReboot(prefs_);
auto ota_successful = OTARebootSucceeded();
@@ -997,6 +1001,11 @@
string current_boot_id;
TEST_AND_RETURN(utils::GetBootId(¤t_boot_id));
prefs_->SetString(kPrefsBootId, current_boot_id);
+ std::string slot_switch_indicator;
+ prefs_->GetString(kPrefsUpdateCompletedOnBootId, &slot_switch_indicator);
+ if (slot_switch_indicator != current_boot_id) {
+ ClearUpdateCompletedMarker();
+ }
// If there's no record of previous version (e.g. due to a data wipe), we
// save the info of current boot and skip the metrics report.
diff --git a/aosp/update_attempter_android.h b/aosp/update_attempter_android.h
index 3174904..956bd25 100644
--- a/aosp/update_attempter_android.h
+++ b/aosp/update_attempter_android.h
@@ -168,8 +168,8 @@
// |update_completed_marker_| is empty.
[[nodiscard]] bool WriteUpdateCompletedMarker();
- // Returns whether an update was completed in the current boot.
- [[nodiscard]] bool UpdateCompletedOnThisBoot();
+ // Returns whether a slot switch was attempted in the current boot.
+ [[nodiscard]] bool UpdateCompletedOnThisBoot() const;
// Prefs to use for metrics report
// |kPrefsPayloadAttemptNumber|: number of update attempts for the current