Make the StartInstall abort-able

The StartInstall may take more than one mintue. This CL adds an
aborting_ flag to notify the allocating procedure to exit once
the flag is set. It also adds a "cancel" command to gsi_tool for
testing purpose.

Test: open two adb consoles: one starts the installation and
    another uses the cancel command to abort.
Bug: 125599267
Change-Id: I8f8fc460df526abda81ed6e0ac8f7176a28e9df3
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 5e786b2..ec5f584 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -254,17 +254,15 @@
 
 binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
     ENFORCE_SYSTEM;
+    should_abort_ = true;
     std::lock_guard<std::mutex> guard(main_lock_);
 
-    if (!installing_) {
-        LOG(ERROR) << "No GSI installation in progress to cancel";
-        *_aidl_return = false;
-        return binder::Status::ok();
+    should_abort_ = false;
+    if (installing_) {
+        PostInstallCleanup();
+        RemoveGsiFiles(install_dir_, wipe_userdata_on_failure_);
     }
 
-    PostInstallCleanup();
-    RemoveGsiFiles(install_dir_, wipe_userdata_on_failure_);
-
     *_aidl_return = true;
     return binder::Status::ok();
 }
@@ -627,6 +625,7 @@
         // TODO: allow cancelling inside cancelGsiInstall.
         progress = [this](uint64_t bytes, uint64_t /* total */) -> bool {
             UpdateProgress(STATUS_WORKING, bytes);
+            if (should_abort_) return false;
             return true;
         };
     }
diff --git a/gsi_service.h b/gsi_service.h
index 272d524..f3cbad0 100644
--- a/gsi_service.h
+++ b/gsi_service.h
@@ -133,6 +133,7 @@
 
     // These are initialized or set in StartInstall().
     bool installing_ = false;
+    std::atomic<bool> should_abort_ = false;
     std::string install_dir_;
     std::string userdata_gsi_path_;
     std::string system_gsi_path_;
diff --git a/gsi_tool.cpp b/gsi_tool.cpp
index 2b8e52a..df2fcd5 100644
--- a/gsi_tool.cpp
+++ b/gsi_tool.cpp
@@ -46,6 +46,7 @@
 static int Install(sp<IGsiService> gsid, int argc, char** argv);
 static int Wipe(sp<IGsiService> gsid, int argc, char** argv);
 static int Status(sp<IGsiService> gsid, int argc, char** argv);
+static int Cancel(sp<IGsiService> gsid, int argc, char** argv);
 
 static const std::map<std::string, CommandCallback> kCommandMap = {
         {"disable", Disable},
@@ -53,6 +54,7 @@
         {"install", Install},
         {"wipe", Wipe},
         {"status", Status},
+        {"cancel", Cancel},
 };
 
 static sp<IGsiService> GetGsiService() {
@@ -355,6 +357,20 @@
     return 0;
 }
 
+static int Cancel(sp<IGsiService> gsid, int /* argc */, char** /* argv */) {
+    bool cancelled = false;
+    auto status = gsid->cancelGsiInstall(&cancelled);
+    if (!status.isOk()) {
+        std::cerr << status.exceptionMessage().string() << std::endl;
+        return EX_SOFTWARE;
+    }
+    if (!cancelled) {
+        std::cout << "Fail to cancel the installation." << std::endl;
+        return EX_SOFTWARE;
+    }
+    return 0;
+}
+
 static int Enable(sp<IGsiService> gsid, int argc, char** argv) {
     bool one_shot = false;
 
@@ -436,7 +452,8 @@
             "               --userdata-size (the latter defaults to 8GiB)\n"
             "               --wipe (remove old gsi userdata first)\n"
             "  wipe         Completely remove a GSI and its associated data\n"
-            "  status       Show status",
+            "  cancel       Cancel the installation\n"
+            "  status       Show status\n",
             argv[0], argv[0]);
     return EX_USAGE;
 }