diff --git a/Android.bp b/Android.bp index b115bc1..af77cef 100644 --- a/Android.bp +++ b/Android.bp @@ -39,6 +39,7 @@ cc_defaults { shared_libs: [ "android.hardware.keymaster@3.0", "android.hardware.keymaster@4.0", + "android.hardware.boot@1.0", "libbase", "libbinder", "libcrypto", diff --git a/Checkpoint.cpp b/Checkpoint.cpp index 995b7ba..1833733 100644 --- a/Checkpoint.cpp +++ b/Checkpoint.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,11 @@ #include #include +using android::hardware::hidl_string; +using android::hardware::boot::V1_0::BoolResult; +using android::hardware::boot::V1_0::IBootControl; +using android::hardware::boot::V1_0::Slot; + namespace android { namespace vold { @@ -61,6 +67,14 @@ bool setBowState(std::string const& block_device, std::string const& state) { bool cp_startCheckpoint(int retry) { if (retry < -1) return false; std::string content = std::to_string(retry); + if (retry == -1) { + sp module = IBootControl::getService(); + if (module) { + std::string suffix; + auto cb = [&suffix](hidl_string s) { suffix = s; }; + if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix; + } + } return android::base::WriteStringToFile(content, kMetadataCPFile); } @@ -100,19 +114,35 @@ void cp_abortChanges() { android_reboot(ANDROID_RB_RESTART2, 0, nullptr); } -bool cp_needRollback(const std::string& id) { +bool cp_needsRollback() { std::string content; bool ret; ret = android::base::ReadFileToString(kMetadataCPFile, &content); - if (ret) return content == "0"; + if (ret) { + if (content == "0") return true; + if (content.substr(0, 3) == "-1 ") { + std::string oldSuffix = content.substr(3); + sp module = IBootControl::getService(); + std::string newSuffix; + + if (module) { + auto cb = [&newSuffix](hidl_string s) { newSuffix = s; }; + module->getSuffix(module->getCurrentSlot(), cb); + if (oldSuffix == newSuffix) return true; + } + } + } return false; } bool cp_needsCheckpoint(void) { bool ret; std::string content; + sp module = IBootControl::getService(); + if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) + return true; ret = android::base::ReadFileToString(kMetadataCPFile, &content); if (ret) return content != "0"; return false; @@ -294,8 +324,9 @@ bool cp_markBootAttempt() { std::string oldContent, newContent; int retry = 0; if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) return false; + std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" ")); - if (!android::base::ParseInt(oldContent, &retry)) return false; + if (!android::base::ParseInt(retryContent, &retry)) return false; if (retry > 0) retry--; newContent = std::to_string(retry); diff --git a/Checkpoint.h b/Checkpoint.h index 81fba99..54574a7 100644 --- a/Checkpoint.h +++ b/Checkpoint.h @@ -28,7 +28,7 @@ bool cp_commitChanges(); void cp_abortChanges(); -bool cp_needRollback(const std::string& id); +bool cp_needsRollback(); bool cp_needsCheckpoint(); diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 41250c7..3884875 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -773,6 +773,14 @@ binder::Status VoldNativeService::startCheckpoint(int32_t retry, bool* _aidl_ret return ok(); } +binder::Status VoldNativeService::needsRollback(bool* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + *_aidl_return = cp_needsRollback(); + return ok(); +} + binder::Status VoldNativeService::needsCheckpoint(bool* _aidl_return) { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; diff --git a/VoldNativeService.h b/VoldNativeService.h index 9a05b45..594c002 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -116,6 +116,7 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status startCheckpoint(int32_t retry, bool* _aidl_return); binder::Status needsCheckpoint(bool* _aidl_return); + binder::Status needsRollback(bool* _aidl_return); binder::Status commitChanges(bool* _aidl_return); binder::Status prepareDriveForCheckpoint(const std::string& mountPoint, bool* _aidl_return); binder::Status restoreCheckpoint(const std::string& mountPoint, bool* _aidl_return); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index f4458a8..27330fe 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -98,6 +98,7 @@ interface IVold { boolean startCheckpoint(int retry); boolean needsCheckpoint(); + boolean needsRollback(); void abortChanges(); boolean commitChanges(); boolean prepareDriveForCheckpoint(@utf8InCpp String mountPoint); diff --git a/vdc.cpp b/vdc.cpp index a080c17..5e2c37a 100644 --- a/vdc.cpp +++ b/vdc.cpp @@ -115,6 +115,10 @@ int main(int argc, char** argv) { bool enabled = false; checkStatus(vold->needsCheckpoint(&enabled)); return enabled ? 1 : 0; + } else if (args[0] == "checkpoint" && args[1] == "needsRollback" && args.size() == 2) { + bool enabled = false; + checkStatus(vold->needsRollback(&enabled)); + return enabled ? 1 : 0; } else if (args[0] == "checkpoint" && args[1] == "commitChanges" && args.size() == 2) { bool success = false; checkStatus(vold->commitChanges(&success));