OSDN Git Service

Add checkpointing support for A/B updates
authorDaniel Rosenberg <drosen@google.com>
Wed, 3 Oct 2018 00:40:44 +0000 (17:40 -0700)
committerDaniel Rosenberg <drosen@google.com>
Wed, 3 Oct 2018 22:39:25 +0000 (15:39 -0700)
This adds implicit rollback support during A/B style updates.
If you explicitly start a checkpoint with -1, needsRollback will
trigger if the update fails, and should be used if any additional
cleanup is needed that is not covered by A/B itself.

Test: All Checkpoint tests pass
Bug: 111020314
Change-Id: I88b4a1098c6bac4dc1438a54c8a8f59577a6c17b

Android.bp
Checkpoint.cpp
Checkpoint.h
VoldNativeService.cpp
VoldNativeService.h
binder/android/os/IVold.aidl
vdc.cpp

index b115bc1..af77cef 100644 (file)
@@ -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",
index d9c0cd1..5d1ec1f 100644 (file)
@@ -26,6 +26,7 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
+#include <android/hardware/boot/1.0/IBootControl.h>
 #include <cutils/android_reboot.h>
 #include <fcntl.h>
 #include <fs_mgr.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 
+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 {
 
@@ -60,6 +66,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<IBootControl> 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);
 }
 
@@ -101,19 +115,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<IBootControl> 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<IBootControl> 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;
@@ -297,8 +327,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);
index 81fba99..54574a7 100644 (file)
@@ -28,7 +28,7 @@ bool cp_commitChanges();
 
 void cp_abortChanges();
 
-bool cp_needRollback(const std::string& id);
+bool cp_needsRollback();
 
 bool cp_needsCheckpoint();
 
index 41250c7..3884875 100644 (file)
@@ -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;
index 9a05b45..594c002 100644 (file)
@@ -116,6 +116,7 @@ class VoldNativeService : public BinderService<VoldNativeService>, 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);
index f4458a8..27330fe 100644 (file)
@@ -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 (file)
--- 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));