summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYi-Yo Chiang <yochiang@google.com>2022-04-04 21:38:57 +0800
committerYi-Yo Chiang <yochiang@google.com>2022-04-04 22:04:56 +0800
commitd646d79c4ff9560a37e2fe494a4c56aa94e76368 (patch)
tree78cadbb95d8ecf7a181d8934e05dc1185ea606b4
parent47f3b0cb4243f1611c8bde4efa7c52d338016e02 (diff)
downloadgsid-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.aidl6
-rw-r--r--gsi_service.cpp74
-rw-r--r--gsi_service.h2
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&);