diff options
author | Yi-Yo Chiang <yochiang@google.com> | 2022-04-04 21:38:57 +0800 |
---|---|---|
committer | Yi-Yo Chiang <yochiang@google.com> | 2022-04-04 22:04:56 +0800 |
commit | d646d79c4ff9560a37e2fe494a4c56aa94e76368 (patch) | |
tree | 78cadbb95d8ecf7a181d8934e05dc1185ea606b4 | |
parent | 47f3b0cb4243f1611c8bde4efa7c52d338016e02 (diff) | |
download | gsid-d646d79c4ff9560a37e2fe494a4c56aa94e76368.tar.gz |
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
-rw-r--r-- | aidl/android/gsi/IGsiService.aidl | 6 | ||||
-rw-r--r-- | gsi_service.cpp | 74 | ||||
-rw-r--r-- | gsi_service.h | 2 |
3 files changed, 39 insertions, 43 deletions
diff --git a/aidl/android/gsi/IGsiService.aidl b/aidl/android/gsi/IGsiService.aidl index c889987..3b5d6c0 100644 --- a/aidl/android/gsi/IGsiService.aidl +++ b/aidl/android/gsi/IGsiService.aidl @@ -74,8 +74,10 @@ interface IGsiService { boolean commitGsiChunkFromAshmem(long bytes); /** - * Complete a GSI installation and mark it as bootable. The caller is - * responsible for rebooting the device as soon as possible. + * Mark a completed DSU installation as bootable. The caller is responsible + * for rebooting the device as soon as possible. + * + * Could leave the installation in "disabled" state if failure. * * @param oneShot If true, the GSI will boot once and then disable itself. * It can still be re-enabled again later with setGsiBootable. 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::setGsiAshmem(const ::android::os::ParcelFileDescripto 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 @@ binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, 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 @@ std::string GsiService::GetInstalledImageDir() { 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 @@ bool GsiService::RemoveGsiFiles(const std::string& install_dir) { 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"; diff --git a/gsi_service.h b/gsi_service.h index 0ec7620..c50c101 100644 --- a/gsi_service.h +++ b/gsi_service.h @@ -92,8 +92,8 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { GsiService(); static int ValidateInstallParams(std::string& install_dir); + int EnableGsi(bool one_shot, const std::string& dsu_slot); bool DisableGsiInstall(); - int ReenableGsi(bool one_shot); static void CleanCorruptedInstallation(); static int SaveInstallation(const std::string&); static bool IsInstallationComplete(const std::string&); |