Change abortChanges to take a message and bool
abortChanges will attempt to pass a reboot message, and will only reboot
if the device is currently checkpointing. Additionally, it can opt to
attempt to prevent future attempts. This only works for non-bootloader
controlled updates. Failures are ignored, as it will always reboot the
device. In the unlikely event of such a failure, the device will
continue to retry as though you did not ask to prevent future attempts.
Test: vdc checkpoint abortChanges abort_retry_test 1
vdc checkpoint abortChanges abort_noretry_test 0
Change-Id: I7b6214765a1faaf4fd193c73331696b53ae572d2
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 30d88ae..1762521 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -180,9 +180,37 @@
return Status::ok();
}
-Status cp_abortChanges() {
- android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
- return Status::ok();
+namespace {
+void abort_metadata_file() {
+ std::string oldContent, newContent;
+ int retry = 0;
+ struct stat st;
+ int result = stat(kMetadataCPFile.c_str(), &st);
+
+ // If the file doesn't exist, we aren't managing a checkpoint retry counter
+ if (result != 0) return;
+ if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
+ PLOG(ERROR) << "Failed to read checkpoint file";
+ return;
+ }
+ std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
+
+ if (!android::base::ParseInt(retryContent, &retry)) {
+ PLOG(ERROR) << "Could not parse retry count";
+ return;
+ }
+ if (retry > 0) {
+ newContent = "0";
+ if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
+ PLOG(ERROR) << "Could not write checkpoint file";
+ }
+}
+} // namespace
+
+void cp_abortChanges(const std::string& message, bool retry) {
+ if (!cp_needsCheckpoint()) return;
+ if (!retry) abort_metadata_file();
+ android_reboot(ANDROID_RB_RESTART2, 0, message.c_str());
}
bool cp_needsRollback() {
diff --git a/Checkpoint.h b/Checkpoint.h
index d077d19..63ead83 100644
--- a/Checkpoint.h
+++ b/Checkpoint.h
@@ -33,7 +33,7 @@
android::binder::Status cp_commitChanges();
-android::binder::Status cp_abortChanges();
+void cp_abortChanges(const std::string& message, bool retry);
bool cp_needsRollback();
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 6868c83..623cced 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -865,11 +865,12 @@
return cp_markBootAttempt();
}
-binder::Status VoldNativeService::abortChanges() {
+binder::Status VoldNativeService::abortChanges(const std::string& message, bool retry) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
- return cp_abortChanges();
+ cp_abortChanges(message, retry);
+ return ok();
}
binder::Status VoldNativeService::supportsCheckpoint(bool* _aidl_return) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 8fbc32d..b90c5b8 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -129,7 +129,7 @@
binder::Status restoreCheckpoint(const std::string& mountPoint);
binder::Status restoreCheckpointPart(const std::string& mountPoint, int count);
binder::Status markBootAttempt();
- binder::Status abortChanges();
+ binder::Status abortChanges(const std::string& message, bool retry);
binder::Status supportsCheckpoint(bool* _aidl_return);
binder::Status supportsBlockCheckpoint(bool* _aidl_return);
binder::Status supportsFileCheckpoint(bool* _aidl_return);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 3c5ef78..72f2643 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -99,7 +99,7 @@
void startCheckpoint(int retry);
boolean needsCheckpoint();
boolean needsRollback();
- void abortChanges();
+ void abortChanges(in @utf8InCpp String device, boolean retry);
void commitChanges();
void prepareCheckpoint();
void restoreCheckpoint(@utf8InCpp String device);
diff --git a/vdc.cpp b/vdc.cpp
index 1ec46c8..76eca3e 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -141,8 +141,10 @@
checkStatus(vold->restoreCheckpointPart(args[2], count));
} else if (args[0] == "checkpoint" && args[1] == "markBootAttempt" && args.size() == 2) {
checkStatus(vold->markBootAttempt());
- } else if (args[0] == "checkpoint" && args[1] == "abortChanges" && args.size() == 2) {
- checkStatus(vold->abortChanges());
+ } else if (args[0] == "checkpoint" && args[1] == "abortChanges" && args.size() == 4) {
+ int retry;
+ if (!android::base::ParseInt(args[2], &retry)) exit(EINVAL);
+ checkStatus(vold->abortChanges(args[2], retry != 0));
} else {
LOG(ERROR) << "Raw commands are no longer supported";
exit(EINVAL);