gsid: Make enableGsi() idempotent
Right now doing this leads to an error:
$ gsi_tool disable # success
$ gsi_tool enable # success
$ gsi_tool enable # failure!
because enableGsi() fails if the DSU/GSI installation is already
enabled. This makes switching boot modes rather inconvenient:
$ gsi_tool enable
$ gsi_tool disable # else "enable -s" would fail
$ gsi_tool enable -s
And cause the following workflow a catastrophic failure:
$ Install DSU/GSI with DynamicSystemInstallationService
$ gsi_tool enable
$ Click DynamicSystemInstallationService "Restart"
$ => "Restart" would call gsid::enableGsi() which would fail,
causing the entire DSU installation to be discarded.
This CL makes the above two cases work without error, by making
enableGsi() idempotent, so that successive calls of enableGsi() wouldn't
fail.
Bug: 220978519
Bug: 225310919
Test: Install DSU with DynamicSystemInstallationService
gsi_tool enable
Click DynamicSystemInstallationService "Restart"
=> no failure and boots into GSI with one-shot mode
Change-Id: I8c37d9577dc0da7c13c1a260fa6ace0990c071b1
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 122bbf6..3392a1d 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -314,12 +314,10 @@
binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
const sp<IGsiServiceCallback>& resultCallback) {
- int result;
- auto status = enableGsi(one_shot, dsuSlot, &result);
- if (!status.isOk()) {
- LOG(ERROR) << "Could not enableGsi: " << status.exceptionMessage().string();
- result = IGsiService::INSTALL_ERROR_GENERIC;
- }
+ ENFORCE_SYSTEM_OR_SHELL;
+ std::lock_guard<std::mutex> guard(lock_);
+
+ const auto result = EnableGsi(one_shot, dsuSlot);
resultCallback->onResult(result);
return binder::Status::ok();
}
@@ -328,20 +326,7 @@
ENFORCE_SYSTEM_OR_SHELL;
std::lock_guard<std::mutex> guard(lock_);
- if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) {
- PLOG(ERROR) << "write failed: " << GetDsuSlot(install_dir_);
- *_aidl_return = INSTALL_ERROR_GENERIC;
- return binder::Status::ok();
- }
- RestoreconMetadataFiles();
-
- if (installer_) {
- LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?";
- *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
- return binder::Status::ok();
- }
-
- *_aidl_return = ReenableGsi(one_shot);
+ *_aidl_return = EnableGsi(one_shot, dsuSlot);
return binder::Status::ok();
}
@@ -946,26 +931,6 @@
return kDefaultDsuImageFolder;
}
-int GsiService::ReenableGsi(bool one_shot) {
- if (!android::gsi::IsGsiInstalled()) {
- LOG(ERROR) << "no gsi installed - cannot re-enable";
- return INSTALL_ERROR_GENERIC;
- }
- std::string boot_key;
- if (!GetInstallStatus(&boot_key)) {
- PLOG(ERROR) << "read " << kDsuInstallStatusFile;
- return INSTALL_ERROR_GENERIC;
- }
- if (boot_key != kInstallStatusDisabled) {
- LOG(ERROR) << "GSI is not currently disabled";
- return INSTALL_ERROR_GENERIC;
- }
- if (!SetBootMode(one_shot) || !ResetBootAttemptCounter()) {
- return IGsiService::INSTALL_ERROR_GENERIC;
- }
- return IGsiService::INSTALL_OK;
-}
-
static android::sp<android::os::IVold> GetVoldService() {
return android::waitForService<android::os::IVold>(android::String16("vold"));
}
@@ -1021,6 +986,35 @@
return ok;
}
+int GsiService::EnableGsi(bool one_shot, const std::string& dsu_slot) {
+ if (!android::gsi::IsGsiInstalled()) {
+ LOG(ERROR) << "no gsi installed - cannot enable";
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ if (installer_) {
+ LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?";
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+
+ if (!DisableGsi()) {
+ PLOG(ERROR) << "cannot write DSU status file";
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ if (!SetBootMode(one_shot)) {
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ if (!ResetBootAttemptCounter()) {
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+
+ if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
+ PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ RestoreconMetadataFiles();
+ return IGsiService::INSTALL_OK;
+}
+
bool GsiService::DisableGsiInstall() {
if (!android::gsi::IsGsiInstalled()) {
LOG(ERROR) << "cannot disable gsi install - no install detected";