diff options
author | Howard Chen <howardsoc@google.com> | 2020-01-16 05:33:09 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-01-16 05:33:09 +0000 |
commit | 32af40977e9153036141a785e09a1e926584ff74 (patch) | |
tree | 3506036d8e1808d8c0a90b9561146cc041571ae6 | |
parent | 24e5af4e7275674d1c4575ff8037e306bb590d83 (diff) | |
parent | ee5c2b14b2f7c1ffbbcc7c6261aa3b5f79362959 (diff) | |
download | gsid-32af40977e9153036141a785e09a1e926584ff74.tar.gz |
Merge "Support multiple DSU installations"
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | aidl/android/gsi/IGsiService.aidl | 14 | ||||
-rw-r--r-- | file_paths.h | 12 | ||||
-rw-r--r-- | gsi_service.cpp | 129 | ||||
-rw-r--r-- | gsi_service.h | 7 | ||||
-rw-r--r-- | gsi_tool.cpp | 62 | ||||
-rw-r--r-- | include/libgsi/libgsi.h | 24 | ||||
-rw-r--r-- | libgsi.cpp | 11 | ||||
-rw-r--r-- | partition_installer.cpp | 23 | ||||
-rw-r--r-- | partition_installer.h | 6 |
10 files changed, 226 insertions, 63 deletions
@@ -103,6 +103,7 @@ cc_binary { "libgsid", "liblp", "libutils", + "libc++fs", ], local_include_dirs: ["include"], } diff --git a/aidl/android/gsi/IGsiService.aidl b/aidl/android/gsi/IGsiService.aidl index 11ea3f5..cd48c63 100644 --- a/aidl/android/gsi/IGsiService.aidl +++ b/aidl/android/gsi/IGsiService.aidl @@ -77,10 +77,12 @@ interface IGsiService { * * @param oneShot If true, the GSI will boot once and then disable itself. * It can still be re-enabled again later with setGsiBootable. + * @param dsuSlot The DSU slot to be enabled. Possible values are available + * with the getInstalledDsuSlots() * * @return INSTALL_* error code. */ - int enableGsi(boolean oneShot); + int enableGsi(boolean oneShot, @utf8InCpp String dsuSlot); /** * @return True if Gsi is enabled @@ -122,12 +124,22 @@ interface IGsiService { boolean isGsiRunning(); /** + * Returns the active DSU slot if there is any DSU installed, empty string otherwise. + */ + @utf8InCpp String getActiveDsuSlot(); + + /** * If a GSI is installed, returns the directory where the installed images * are located. Otherwise, returns an empty string. */ @utf8InCpp String getInstalledGsiImageDir(); /** + * Returns all installed DSU slots. + */ + @utf8InCpp List<String> getInstalledDsuSlots(); + + /** * Open a DSU installation * * @param installDir The directory to install DSU images under. This must be diff --git a/file_paths.h b/file_paths.h index b596704..1ae7817 100644 --- a/file_paths.h +++ b/file_paths.h @@ -16,22 +16,26 @@ #pragma once +#include <filesystem> + namespace android { namespace gsi { static constexpr char kDefaultDsuImageFolder[] = "/data/gsi/dsu/"; static constexpr char kUserdataDevice[] = "/dev/block/by-name/userdata"; -static constexpr char kDsuMetadataDir[] = "/metadata/gsi/dsu"; -static constexpr char kDsuOneShotBootFile[] = "/metadata/gsi/dsu/one_shot_boot"; -static constexpr char kDsuInstallDirFile[] = "/metadata/gsi/dsu/install_dir"; +static inline std::string MetadataDir(const std::string& dsu_slot) { + return std::filesystem::path(DSU_METADATA_PREFIX) / dsu_slot; +} + +static constexpr char kDsuOneShotBootFile[] = DSU_METADATA_PREFIX "one_shot_boot"; // This file can contain the following values: // [int] - boot attempt counter, starting from 0 // "ok" - boot was marked successful // "disabled" - boot into GSI no longer allowed // "wipe" - boot into GSI not allowed; next reboot will delete gsi -static constexpr char kDsuInstallStatusFile[] = "/metadata/gsi/dsu/install_status"; +static constexpr char kDsuInstallStatusFile[] = DSU_METADATA_PREFIX "install_status"; } // namespace gsi } // namespace android diff --git a/gsi_service.cpp b/gsi_service.cpp index fd39e7f..8a77f4f 100644 --- a/gsi_service.cpp +++ b/gsi_service.cpp @@ -53,7 +53,6 @@ using namespace android::fs_mgr; using namespace android::fiemap; using android::base::ReadFileToString; using android::base::RemoveFileIfExists; -using android::base::Split; using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteStringToFd; @@ -116,10 +115,19 @@ android::sp<IGsiService> GsiService::Get(Gsid* parent) { } while (0) int GsiService::SaveInstallation(const std::string& installation) { + auto dsu_slot = GetDsuSlot(installation); + auto install_dir_file = DsuInstallDirFile(dsu_slot); + auto metadata_dir = android::base::Dirname(install_dir_file); + if (access(metadata_dir.c_str(), F_OK) != 0) { + if (mkdir(metadata_dir.c_str(), 0777) != 0) { + PLOG(ERROR) << "Failed to mkdir " << metadata_dir; + return INSTALL_ERROR_GENERIC; + } + } auto fd = android::base::unique_fd( - open(kDsuInstallDirFile, O_RDWR | O_SYNC | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + open(install_dir_file.c_str(), O_RDWR | O_SYNC | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); if (!WriteStringToFd(installation, fd)) { - PLOG(ERROR) << "write failed: " << kDsuInstallDirFile; + PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot); return INSTALL_ERROR_GENERIC; } return INSTALL_OK; @@ -138,7 +146,8 @@ binder::Status GsiService::openInstall(const std::string& install_dir, int* _aid return binder::Status::ok(); } std::string message; - if (!RemoveFileIfExists(GetCompleteIndication(install_dir_), &message)) { + auto dsu_slot = GetDsuSlot(install_dir_); + if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) { LOG(ERROR) << message; } // Remember the installation directory before allocate any resource @@ -149,12 +158,12 @@ binder::Status GsiService::openInstall(const std::string& install_dir, int* _aid binder::Status GsiService::closeInstall(int* _aidl_return) { ENFORCE_SYSTEM; std::lock_guard<std::mutex> guard(parent_->lock()); - std::string file = GetCompleteIndication(install_dir_); + auto dsu_slot = GetDsuSlot(install_dir_); + std::string file = GetCompleteIndication(dsu_slot); if (!WriteStringToFile("OK", file)) { PLOG(ERROR) << "write failed: " << file; *_aidl_return = INSTALL_ERROR_GENERIC; } - install_dir_ = {}; *_aidl_return = INSTALL_OK; return binder::Status::ok(); } @@ -184,7 +193,8 @@ binder::Status GsiService::createPartition(const ::std::string& name, int64_t si if (size == 0 && name == "userdata") { size = kDefaultUserdataSize; } - installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name, size, readOnly); + installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name, + GetDsuSlot(install_dir_), size, readOnly); int status = installer_->StartInstall(); if (status != INSTALL_OK) { installer_ = nullptr; @@ -249,6 +259,7 @@ binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_r binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem, int64_t size, bool* _aidl_return) { + ENFORCE_SYSTEM; if (!installer_) { *_aidl_return = false; return binder::Status::ok(); @@ -257,9 +268,14 @@ binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescripto return binder::Status::ok(); } -binder::Status GsiService::enableGsi(bool one_shot, int* _aidl_return) { +binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) { std::lock_guard<std::mutex> guard(parent_->lock()); + if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) { + PLOG(ERROR) << "write failed: " << GetDsuSlot(install_dir_); + *_aidl_return = INSTALL_ERROR_GENERIC; + return binder::Status::ok(); + } if (installer_) { ENFORCE_SYSTEM; installer_ = {}; @@ -286,7 +302,7 @@ binder::Status GsiService::isGsiEnabled(bool* _aidl_return) { if (!GetInstallStatus(&boot_key)) { *_aidl_return = false; } else { - *_aidl_return = (boot_key == kInstallStatusOk); + *_aidl_return = (boot_key != kInstallStatusDisabled); } return binder::Status::ok(); } @@ -357,6 +373,21 @@ binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) { return binder::Status::ok(); } +binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) { + ENFORCE_SYSTEM_OR_SHELL; + std::lock_guard<std::mutex> guard(parent_->lock()); + + *_aidl_return = GetActiveDsuSlot(); + return binder::Status::ok(); +} + +binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) { + ENFORCE_SYSTEM; + std::lock_guard<std::mutex> guard(parent_->lock()); + *_aidl_return = GetInstalledDsuSlots(); + return binder::Status::ok(); +} + binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) { ENFORCE_SYSTEM_OR_SHELL; std::lock_guard<std::mutex> guard(parent_->lock()); @@ -367,7 +398,7 @@ binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_ret } std::string install_dir = GetActiveInstalledImageDir(); - *_aidl_return = PartitionInstaller::WipeWritable(install_dir, name); + *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name); return binder::Status::ok(); } @@ -607,7 +638,11 @@ binder::Status GsiService::openImageService(const std::string& prefix, auto in_metadata_dir = kImageMetadataPrefix + prefix; auto in_data_dir = kImageDataPrefix + prefix; + auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix)); + if (android::base::ReadFileToString(install_dir_file, &in_data_dir)) { + LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir; + } std::string metadata_dir, data_dir; if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) { PLOG(ERROR) << "realpath failed: " << metadata_dir; @@ -711,6 +746,15 @@ int GsiService::ValidateInstallParams(std::string& install_dir) { return INSTALL_OK; } +std::string GsiService::GetActiveDsuSlot() { + if (!install_dir_.empty()) { + return GetDsuSlot(install_dir_); + } else { + std::string active_dsu; + return GetActiveDsu(&active_dsu) ? active_dsu : ""; + } +} + std::string GsiService::GetActiveInstalledImageDir() { // Just in case an install was left hanging. if (installer_) { @@ -723,8 +767,10 @@ std::string GsiService::GetActiveInstalledImageDir() { std::string GsiService::GetInstalledImageDir() { // If there's no install left, just return /data/gsi since that's where // installs go by default. + std::string active_dsu; std::string dir; - if (android::base::ReadFileToString(kDsuInstallDirFile, &dir)) { + if (GetActiveDsu(&active_dsu) && + android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) { return dir; } return kDefaultDsuImageFolder; @@ -758,10 +804,11 @@ int GsiService::ReenableGsi(bool one_shot) { bool GsiService::RemoveGsiFiles(const std::string& install_dir) { bool ok = true; - if (auto manager = ImageManager::Open(kDsuMetadataDir, install_dir)) { + auto active_dsu = GetDsuSlot(install_dir); + if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) { std::vector<std::string> images = manager->GetAllBackingImages(); for (auto&& image : images) { - if (!android::base::EndsWith(image, "_gsi")) { + if (!android::base::EndsWith(image, kDsuPostfix)) { continue; } if (manager->IsImageMapped(image)) { @@ -770,11 +817,12 @@ bool GsiService::RemoveGsiFiles(const std::string& install_dir) { ok &= manager->DeleteBackingImage(image); } } + auto dsu_slot = GetDsuSlot(install_dir); std::vector<std::string> files{ kDsuInstallStatusFile, kDsuOneShotBootFile, - kDsuInstallDirFile, - GetCompleteIndication(install_dir), + DsuInstallDirFile(dsu_slot), + GetCompleteIndication(dsu_slot), }; for (const auto& file : files) { std::string message; @@ -802,14 +850,15 @@ bool GsiService::DisableGsiInstall() { return true; } -std::string GsiService::GetCompleteIndication(const std::string& installation) { - auto strip_slash = installation.substr(0, installation.size() - 1); - auto prefix = Split(strip_slash, "/").back(); - return "/metadata/gsi/" + prefix + "/complete"; +std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) { + return DSU_METADATA_PREFIX + dsu_slot + "/complete"; } -bool GsiService::IsInstallationComplete(const std::string& install_dir) { - std::string file = GetCompleteIndication(install_dir); +bool GsiService::IsInstallationComplete(const std::string& dsu_slot) { + if (access(kDsuInstallStatusFile, F_OK) != 0) { + return false; + } + std::string file = GetCompleteIndication(dsu_slot); std::string content; if (!ReadFileToString(file, &content)) { return false; @@ -817,12 +866,35 @@ bool GsiService::IsInstallationComplete(const std::string& install_dir) { return content == "OK"; } +std::vector<std::string> GsiService::GetInstalledDsuSlots() { + std::vector<std::string> dsu_slots; + auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir); + if (d != nullptr) { + struct dirent* de; + while ((de = readdir(d.get())) != nullptr) { + if (de->d_name[0] == '.') { + continue; + } + auto dsu_slot = std::string(de->d_name); + if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) { + continue; + } + dsu_slots.push_back(dsu_slot); + } + } + return dsu_slots; +} + void GsiService::CleanCorruptedInstallation() { - auto install_dir = GetInstalledImageDir(); - bool is_complete = IsInstallationComplete(install_dir); - if (!is_complete) { - if (!RemoveGsiFiles(install_dir)) { - LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << install_dir; + for (auto&& slot : GetInstalledDsuSlots()) { + bool is_complete = IsInstallationComplete(slot); + if (!is_complete) { + LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot; + std::string install_dir; + if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) || + !RemoveGsiFiles(install_dir)) { + LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot; + } } } } @@ -830,6 +902,11 @@ void GsiService::CleanCorruptedInstallation() { void GsiService::RunStartupTasks() { CleanCorruptedInstallation(); + std::string active_dsu; + if (!GetActiveDsu(&active_dsu)) { + PLOG(INFO) << "no DSU"; + return; + } std::string boot_key; if (!GetInstallStatus(&boot_key)) { PLOG(ERROR) << "read " << kDsuInstallStatusFile; diff --git a/gsi_service.h b/gsi_service.h index fe70a04..b828899 100644 --- a/gsi_service.h +++ b/gsi_service.h @@ -68,7 +68,7 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { bool* _aidl_return) override; binder::Status commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) override; binder::Status cancelGsiInstall(bool* _aidl_return) override; - binder::Status enableGsi(bool oneShot, int* _aidl_return) override; + binder::Status enableGsi(bool oneShot, const std::string& dsuSlot, int* _aidl_return) override; binder::Status isGsiEnabled(bool* _aidl_return) override; binder::Status removeGsi(bool* _aidl_return) override; binder::Status disableGsi(bool* _aidl_return) override; @@ -76,6 +76,8 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { binder::Status isGsiRunning(bool* _aidl_return) override; binder::Status isGsiInstallInProgress(bool* _aidl_return) override; binder::Status getInstalledGsiImageDir(std::string* _aidl_return) override; + binder::Status getActiveDsuSlot(std::string* _aidl_return) override; + binder::Status getInstalledDsuSlots(std::vector<std::string>* _aidl_return) override; binder::Status zeroPartition(const std::string& name, int* _aidl_return) override; binder::Status openImageService(const std::string& prefix, android::sp<IImageService>* _aidl_return) override; @@ -93,8 +95,11 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { static void RunStartupTasks(); static std::string GetInstalledImageDir(); + std::string GetActiveDsuSlot(); std::string GetActiveInstalledImageDir(); + static std::vector<std::string> GetInstalledDsuSlots(); + private: GsiService(Gsid* parent); static int ValidateInstallParams(std::string& install_dir); diff --git a/gsi_tool.cpp b/gsi_tool.cpp index 6cafd82..9abb1ff 100644 --- a/gsi_tool.cpp +++ b/gsi_tool.cpp @@ -299,8 +299,13 @@ static int Install(sp<IGsiService> gsid, int argc, char** argv) { return EX_SOFTWARE; } progress.Finish(); - - status = gsid->enableGsi(true, &error); + std::string dsuSlot; + status = gsid->getActiveDsuSlot(&dsuSlot); + if (!status.isOk()) { + std::cerr << "Could not get the active DSU slot: " << ErrorMessage(status) << "\n"; + return EX_SOFTWARE; + } + status = gsid->enableGsi(true, dsuSlot, &error); if (!status.isOk() || error != IGsiService::INSTALL_OK) { std::cerr << "Could not make live image bootable: " << ErrorMessage(status, error) << "\n"; return EX_SOFTWARE; @@ -409,21 +414,31 @@ static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) { if (getuid() != 0) { return 0; } - sp<IImageService> image_service = nullptr; - status = gsid->openImageService("dsu", &image_service); - if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; - return EX_SOFTWARE; - } - std::vector<std::string> images; - status = image_service->getAllBackingImages(&images); + + std::vector<std::string> dsu_slots; + status = gsid->getInstalledDsuSlots(&dsu_slots); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << status.exceptionMessage().string() << std::endl; return EX_SOFTWARE; } - - for (auto&& image : images) { - std::cout << "installed: " << image << std::endl; + int n = 0; + for (auto&& dsu_slot : dsu_slots) { + std::cout << "[" << n++ << "] " << dsu_slot << std::endl; + sp<IImageService> image_service = nullptr; + status = gsid->openImageService("dsu/" + dsu_slot + "/", &image_service); + if (!status.isOk()) { + std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + return EX_SOFTWARE; + } + std::vector<std::string> images; + status = image_service->getAllBackingImages(&images); + if (!status.isOk()) { + std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + return EX_SOFTWARE; + } + for (auto&& image : images) { + std::cout << "installed: " << image << std::endl; + } } return 0; } @@ -444,9 +459,10 @@ static int Cancel(sp<IGsiService> gsid, int /* argc */, char** /* argv */) { static int Enable(sp<IGsiService> gsid, int argc, char** argv) { bool one_shot = false; - + std::string dsuSlot = {}; struct option options[] = { {"single-boot", no_argument, nullptr, 's'}, + {"dsuslot", required_argument, nullptr, 'd'}, {nullptr, 0, nullptr, 0}, }; int rv, index; @@ -455,6 +471,9 @@ static int Enable(sp<IGsiService> gsid, int argc, char** argv) { case 's': one_shot = true; break; + case 'd': + dsuSlot = optarg; + break; default: std::cerr << "Unrecognized argument to enable\n"; return EX_USAGE; @@ -474,9 +493,15 @@ static int Enable(sp<IGsiService> gsid, int argc, char** argv) { std::cerr << "Cannot enable or disable while an installation is in progress." << std::endl; return EX_SOFTWARE; } - + if (dsuSlot.empty()) { + auto status = gsid->getActiveDsuSlot(&dsuSlot); + if (!status.isOk()) { + std::cerr << "Could not get the active DSU slot: " << ErrorMessage(status) << "\n"; + return EX_SOFTWARE; + } + } int error; - auto status = gsid->enableGsi(one_shot, &error); + auto status = gsid->enableGsi(one_shot, dsuSlot, &error); if (!status.isOk() || error != IGsiService::INSTALL_OK) { std::cerr << "Error re-enabling GSI: " << ErrorMessage(status, error) << "\n"; return EX_SOFTWARE; @@ -516,7 +541,8 @@ static int usage(int /* argc */, char* argv[]) { " %s <disable|install|wipe|status> [options]\n" "\n" " disable Disable the currently installed GSI.\n" - " enable [-s, --single-boot]\n" + " enable [-s, --single-boot]\n" + " [-d, --dsuslot slotname]\n" " Enable a previously disabled GSI.\n" " install Install a new GSI. Specify the image size with\n" " --gsi-size and the desired userdata size with\n" diff --git a/include/libgsi/libgsi.h b/include/libgsi/libgsi.h index 9b24f47..987797a 100644 --- a/include/libgsi/libgsi.h +++ b/include/libgsi/libgsi.h @@ -23,11 +23,25 @@ namespace gsi { static constexpr char kGsiServiceName[] = "gsiservice"; -static constexpr char kGsiBootedIndicatorFile[] = "/metadata/gsi/dsu/booted"; +#define DSU_METADATA_PREFIX "/metadata/gsi/dsu/" -static constexpr char kGsiLpNamesFile[] = "/metadata/gsi/dsu/lp_names"; +static constexpr char kGsiBootedIndicatorFile[] = DSU_METADATA_PREFIX "booted"; -static constexpr char kDsuLpMetadataFile[] = "/metadata/gsi/dsu/lp_metadata"; +static constexpr char kGsiLpNamesFile[] = DSU_METADATA_PREFIX "lp_names"; + +static constexpr char kDsuActiveFile[] = DSU_METADATA_PREFIX "active"; + +static inline std::string DsuLpMetadataFile(const std::string& dsu_slot) { + return DSU_METADATA_PREFIX + dsu_slot + "/lp_metadata"; +} + +static inline std::string DsuInstallDirFile(const std::string& dsu_slot) { + return DSU_METADATA_PREFIX + dsu_slot + "/install_dir"; +} + +// install_dir "/data/gsi/dsu/dsu" has a slot name "dsu" +// install_dir "/data/gsi/dsu/dsu2" has a slot name "dsu2" +std::string GetDsuSlot(const std::string& install_dir); static constexpr char kGsiBootedProp[] = "ro.gsid.image_running"; @@ -35,6 +49,10 @@ static constexpr char kDsuPostfix[] = "_gsi"; static constexpr int kMaxBootAttempts = 1; +// Get the currently active dsu slot +// Return true on success +bool GetActiveDsu(std::string* active_dsu); + // Returns true if the currently running system image is a live GSI. bool IsGsiRunning(); @@ -23,6 +23,7 @@ #include <android-base/file.h> #include <android-base/parseint.h> +#include <android-base/strings.h> #include <android-base/unique_fd.h> #include "file_paths.h" @@ -32,8 +33,14 @@ namespace android { namespace gsi { using namespace std::literals; +using android::base::ReadFileToString; +using android::base::Split; using android::base::unique_fd; +bool GetActiveDsu(std::string* active_dsu) { + return android::base::ReadFileToString(kDsuActiveFile, active_dsu); +} + bool IsGsiRunning() { return !access(kGsiBootedIndicatorFile, F_OK); } @@ -53,6 +60,10 @@ static bool WriteAndSyncFile(const std::string& data, const std::string& file) { return fsync(fd) == 0; } +std::string GetDsuSlot(const std::string& install_dir) { + return android::base::Basename(install_dir); +} + bool CanBootIntoGsi(std::string* error) { // Always delete this as a safety precaution, so we can return to the // original system image. If we're confident GSI will boot, this will diff --git a/partition_installer.cpp b/partition_installer.cpp index 8e67420..ff2cc59 100644 --- a/partition_installer.cpp +++ b/partition_installer.cpp @@ -44,9 +44,15 @@ using android::base::unique_fd; static constexpr uint32_t kMinimumFreeSpaceThreshold = 40; PartitionInstaller::PartitionInstaller(GsiService* service, const std::string& install_dir, - const std::string& name, int64_t size, bool read_only) - : service_(service), install_dir_(install_dir), name_(name), size_(size), readOnly_(read_only) { - images_ = ImageManager::Open(kDsuMetadataDir, install_dir_); + const std::string& name, const std::string& active_dsu, + int64_t size, bool read_only) + : service_(service), + install_dir_(install_dir), + name_(name), + active_dsu_(active_dsu), + size_(size), + readOnly_(read_only) { + images_ = ImageManager::Open(MetadataDir(active_dsu), install_dir_); } PartitionInstaller::~PartitionInstaller() { @@ -62,7 +68,7 @@ PartitionInstaller::~PartitionInstaller() { } void PartitionInstaller::PostInstallCleanup() { - auto manager = ImageManager::Open(kDsuMetadataDir, GsiService::GetInstalledImageDir()); + auto manager = ImageManager::Open(MetadataDir(active_dsu_), install_dir_); if (!manager) { LOG(ERROR) << "Could not open image manager"; return; @@ -299,13 +305,13 @@ bool PartitionInstaller::Format() { } int PartitionInstaller::Finish() { - if (!readOnly_ && gsi_bytes_written_ != size_) { + if (readOnly_ && gsi_bytes_written_ != size_) { // We cannot boot if the image is incomplete. LOG(ERROR) << "image incomplete; expected " << size_ << " bytes, waiting for " << (size_ - gsi_bytes_written_) << " bytes"; return IGsiService::INSTALL_ERROR_GENERIC; } - if (fsync(system_device_->fd())) { + if (system_device_ != nullptr && fsync(system_device_->fd())) { PLOG(ERROR) << "fsync failed for " << name_ << "_gsi"; return IGsiService::INSTALL_ERROR_GENERIC; } @@ -321,8 +327,9 @@ int PartitionInstaller::Finish() { return IGsiService::INSTALL_OK; } -int PartitionInstaller::WipeWritable(const std::string& install_dir, const std::string& name) { - auto image = ImageManager::Open(kDsuMetadataDir, install_dir); +int PartitionInstaller::WipeWritable(const std::string& active_dsu, const std::string& install_dir, + const std::string& name) { + auto image = ImageManager::Open(MetadataDir(active_dsu), install_dir); // The device object has to be destroyed before the image object auto device = MappedDevice::Open(image.get(), 10s, name); if (!device) { diff --git a/partition_installer.h b/partition_installer.h index 787eda4..830c034 100644 --- a/partition_installer.h +++ b/partition_installer.h @@ -39,7 +39,7 @@ class PartitionInstaller final { public: // Constructor for a new GSI installation. PartitionInstaller(GsiService* service, const std::string& installDir, const std::string& name, - int64_t size, bool read_only); + const std::string& active_dsu, int64_t size, bool read_only); ~PartitionInstaller(); // Methods for a clean GSI install. @@ -49,7 +49,8 @@ class PartitionInstaller final { bool MapAshmem(int fd, size_t size); bool CommitGsiChunk(size_t bytes); - static int WipeWritable(const std::string& install_dir, const std::string& name); + static int WipeWritable(const std::string& active_dsu, const std::string& install_dir, + const std::string& name); // Clean up install state if gsid crashed and restarted. void PostInstallCleanup(); @@ -74,6 +75,7 @@ class PartitionInstaller final { std::string install_dir_; std::string name_; + std::string active_dsu_; std::unique_ptr<ImageManager> images_; uint64_t size_ = 0; bool readOnly_; |