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
This commit is contained in:
Daniel Rosenberg 2019-03-20 17:02:47 -07:00
parent 84203c1e24
commit a59e4396a4
6 changed files with 41 additions and 10 deletions

View file

@ -180,9 +180,37 @@ Status cp_commitChanges() {
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() {

View file

@ -33,7 +33,7 @@ android::binder::Status cp_startCheckpoint(int retry);
android::binder::Status cp_commitChanges();
android::binder::Status cp_abortChanges();
void cp_abortChanges(const std::string& message, bool retry);
bool cp_needsRollback();

View file

@ -865,11 +865,12 @@ binder::Status VoldNativeService::markBootAttempt() {
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) {

View file

@ -129,7 +129,7 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
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);

View file

@ -99,7 +99,7 @@ interface IVold {
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);

View file

@ -141,8 +141,10 @@ int main(int argc, char** argv) {
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);