Refactor gsid to separate the installer code.
GsiService is getting to be pretty unreadable, in part because it's a
lot of code, but also because it mixes a lot of state in with the rest
of GsiService. It's not always clear when it's okay for GsiService to
rely on state set by the install process.
To make this much more clear, this patch separates all the installer
code into a separate GsiInstaller class, which has its own header and
source files. GsiService will instantiate a GsiInstaller as needed and
destroy it to either cancel or complete an install. As an added bonus,
install cleanup can now be handled in the GsiInstaller destructor,
rather than on an ad-hoc basis in GsiService.
Bug: N/A
Test: gsi_tool install
gsi_tool disable
gsi_tool enable
gsi_tool wipe
gsi_tool cancel
Change-Id: I26b2a48487a1df903d1805de80b0c6f2a074f997
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 7b30d0b..24a741b 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -20,7 +20,6 @@
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>
@@ -35,11 +34,6 @@
#include <android-base/strings.h>
#include <android/gsi/IGsiService.h>
#include <fs_mgr.h>
-#include <fs_mgr_dm_linear.h>
-#include <fstab/fstab.h>
-#include <libdm/dm.h>
-#include <libfiemap_writer/fiemap_writer.h>
-#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
#include "file_paths.h"
@@ -49,25 +43,11 @@
namespace gsi {
using namespace std::literals;
-using namespace android::dm;
using namespace android::fs_mgr;
using namespace android::fiemap_writer;
using android::base::StringPrintf;
using android::base::unique_fd;
-static constexpr char kGsiDataFolder[] = "/data/gsi/";
-static constexpr char kUserdataDevice[] = "/dev/block/by-name/userdata";
-
-// The default size of userdata.img for GSI.
-// We are looking for /data to have atleast 40% free space
-static constexpr uint32_t kMinimumFreeSpaceThreshold = 40;
-// We determine the fragmentation by making sure the files
-// we create don't have more than 16 extents.
-static constexpr uint32_t kMaximumExtents = 512;
-// Default userdata image size.
-static constexpr int64_t kDefaultUserdataSize = int64_t(8) * 1024 * 1024 * 1024;
-static constexpr std::chrono::milliseconds kDmTimeout = 5000ms;
-
void GsiService::Register() {
auto ret = android::BinderService<GsiService>::publish();
if (ret != android::OK) {
@@ -77,11 +57,10 @@
GsiService::GsiService() {
progress_ = {};
+ GsiInstaller::PostInstallCleanup();
}
-GsiService::~GsiService() {
- PostInstallCleanup();
-}
+GsiService::~GsiService() {}
#define ENFORCE_SYSTEM \
do { \
@@ -110,7 +89,7 @@
std::lock_guard<std::mutex> guard(main_lock_);
// Make sure any interrupted installations are cleaned up.
- PostInstallCleanup();
+ installer_ = nullptr;
// Do some precursor validation on the arguments before diving into the
// install process.
@@ -120,16 +99,12 @@
return binder::Status::ok();
}
- int status = StartInstall(params);
+ installer_ = std::make_unique<GsiInstaller>(this, params);
+ int status = installer_->StartInstall();
if (status != INSTALL_OK) {
- // Perform local cleanup and delete any lingering files.
- PostInstallCleanup();
- RemoveGsiFiles(params.installDir, wipe_userdata_on_failure_);
+ installer_ = nullptr;
}
*_aidl_return = status;
-
- // Clear the progress indicator.
- UpdateProgress(STATUS_NO_OPERATION, 0);
return binder::Status::ok();
}
@@ -138,10 +113,12 @@
ENFORCE_SYSTEM;
std::lock_guard<std::mutex> guard(main_lock_);
- *_aidl_return = CommitGsiChunk(stream.get(), bytes);
+ if (!installer_) {
+ *_aidl_return = false;
+ return binder::Status::ok();
+ }
- // Clear the progress indicator.
- UpdateProgress(STATUS_NO_OPERATION, 0);
+ *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
return binder::Status::ok();
}
@@ -178,19 +155,21 @@
ENFORCE_SYSTEM;
std::lock_guard<std::mutex> guard(main_lock_);
- *_aidl_return = CommitGsiChunk(bytes.data(), bytes.size());
+ if (!installer_) {
+ *_aidl_return = false;
+ return binder::Status::ok();
+ }
+
+ *_aidl_return = installer_->CommitGsiChunk(bytes.data(), bytes.size());
return binder::Status::ok();
}
binder::Status GsiService::setGsiBootable(bool one_shot, int* _aidl_return) {
std::lock_guard<std::mutex> guard(main_lock_);
- if (installing_) {
+ if (installer_) {
ENFORCE_SYSTEM;
- int error = SetGsiBootable(one_shot);
- PostInstallCleanup();
- if (error) {
- RemoveGsiFiles(install_dir_, wipe_userdata_on_failure_);
+ if (int error = installer_->SetGsiBootable(one_shot)) {
*_aidl_return = error;
} else {
*_aidl_return = INSTALL_OK;
@@ -198,9 +177,9 @@
} else {
ENFORCE_SYSTEM_OR_SHELL;
*_aidl_return = ReenableGsi(one_shot);
- PostInstallCleanup();
}
+ installer_ = nullptr;
return binder::Status::ok();
}
@@ -222,9 +201,8 @@
// Just in case an install was left hanging.
std::string install_dir;
- if (installing_) {
- install_dir = install_dir_;
- PostInstallCleanup();
+ if (installer_) {
+ install_dir = installer_->install_dir();
} else {
install_dir = GetInstalledImageDir();
}
@@ -266,7 +244,7 @@
ENFORCE_SYSTEM_OR_SHELL;
std::lock_guard<std::mutex> guard(main_lock_);
- *_aidl_return = installing_;
+ *_aidl_return = !!installer_;
return binder::Status::ok();
}
@@ -276,10 +254,7 @@
std::lock_guard<std::mutex> guard(main_lock_);
should_abort_ = false;
- if (installing_) {
- PostInstallCleanup();
- RemoveGsiFiles(install_dir_, wipe_userdata_on_failure_);
- }
+ installer_ = nullptr;
*_aidl_return = true;
return binder::Status::ok();
@@ -330,9 +305,9 @@
*_aidl_return = -1;
- if (installing_) {
+ if (installer_) {
// Size has already been computed.
- *_aidl_return = userdata_size_;
+ *_aidl_return = installer_->userdata_size();
} else if (IsGsiRunning()) {
// :TODO: libdm
unique_fd fd(open(kUserdataDevice, O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
@@ -391,22 +366,6 @@
return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
}
-void GsiService::PostInstallCleanup() {
- // This must be closed before unmapping partitions.
- system_writer_ = nullptr;
-
- const auto& dm = DeviceMapper::Instance();
- if (dm.GetState("userdata_gsi") != DmDeviceState::INVALID) {
- DestroyLogicalPartition("userdata_gsi", kDmTimeout);
- }
- if (dm.GetState("system_gsi") != DmDeviceState::INVALID) {
- DestroyLogicalPartition("system_gsi", kDmTimeout);
- }
-
- installing_ = false;
- partitions_.clear();
-}
-
static bool IsExternalStoragePath(const std::string& path) {
if (!android::base::StartsWith(path, "/mnt/media_rw/")) {
return false;
@@ -476,69 +435,6 @@
return INSTALL_OK;
}
-int GsiService::StartInstall(const GsiInstallParams& params) {
- installing_ = true;
- userdata_block_size_ = 0;
- system_block_size_ = 0;
- gsi_size_ = params.gsiSize;
- userdata_size_ = (params.userdataSize) ? params.userdataSize : kDefaultUserdataSize;
- wipe_userdata_ = params.wipeUserdata;
- can_use_devicemapper_ = false;
- gsi_bytes_written_ = 0;
- install_dir_ = params.installDir;
-
- userdata_gsi_path_ = GetImagePath(install_dir_, "userdata_gsi");
- system_gsi_path_ = GetImagePath(install_dir_, "system_gsi");
-
- // Only rm userdata_gsi if one didn't already exist.
- wipe_userdata_on_failure_ = wipe_userdata_ || access(userdata_gsi_path_.c_str(), F_OK);
-
- if (int status = PerformSanityChecks()) {
- return status;
- }
- if (int status = PreallocateFiles()) {
- return status;
- }
- if (int status = DetermineReadWriteMethod()) {
- return status;
- }
- if (!FormatUserdata()) {
- return INSTALL_ERROR_GENERIC;
- }
-
- // Map system_gsi so we can write to it.
- system_writer_ = OpenPartition("system_gsi");
- if (!system_writer_) {
- return INSTALL_ERROR_GENERIC;
- }
- return INSTALL_OK;
-}
-
-int GsiService::DetermineReadWriteMethod() {
- // If there is a device-mapper node wrapping the block device, then we're
- // able to create another node around it; the dm layer does not carry the
- // exclusion lock down the stack when a mount occurs.
- //
- // If there is no intermediate device-mapper node, then partitions cannot be
- // opened writable due to sepolicy and exclusivity of having a mounted
- // filesystem. This should only happen on devices with no encryption, or
- // devices with FBE and no metadata encryption. For these cases it suffices
- // to perform normal file writes to /data/gsi (which is unencrypted).
- std::string block_device;
- if (!FiemapWriter::GetBlockDeviceForFile(system_gsi_path_.c_str(), &block_device,
- &can_use_devicemapper_)) {
- return INSTALL_ERROR_GENERIC;
- }
- if (install_dir_ != kGsiDataFolder && can_use_devicemapper_) {
- // Never use device-mapper on external media. We don't support adopted
- // storage yet, and accidentally using device-mapper could be dangerous
- // as we hardcode the userdata device as backing storage.
- LOG(ERROR) << "unexpected device-mapper node used to mount external media";
- return INSTALL_ERROR_GENERIC;
- }
- return INSTALL_OK;
-}
-
std::string GsiService::GetImagePath(const std::string& image_dir, const std::string& name) {
std::string dir = image_dir;
if (!android::base::EndsWith(dir, "/")) {
@@ -561,309 +457,6 @@
return GetImagePath(GetInstalledImageDir(), name);
}
-int GsiService::PerformSanityChecks() {
- if (gsi_size_ < 0) {
- LOG(ERROR) << "image size " << gsi_size_ << " is negative";
- return INSTALL_ERROR_GENERIC;
- }
- if (android::gsi::IsGsiRunning()) {
- LOG(ERROR) << "cannot install gsi inside a live gsi";
- return INSTALL_ERROR_GENERIC;
- }
-
- struct statvfs sb;
- if (statvfs(install_dir_.c_str(), &sb)) {
- PLOG(ERROR) << "failed to read file system stats";
- return INSTALL_ERROR_GENERIC;
- }
-
- // This is the same as android::vold::GetFreebytes() but we also
- // need the total file system size so we open code it here.
- uint64_t free_space = 1ULL * sb.f_bavail * sb.f_frsize;
- uint64_t fs_size = sb.f_blocks * sb.f_frsize;
- if (free_space <= (gsi_size_ + userdata_size_)) {
- LOG(ERROR) << "not enough free space (only " << free_space << " bytes available)";
- return INSTALL_ERROR_NO_SPACE;
- }
- // We are asking for 40% of the /data to be empty.
- // TODO: may be not hard code it like this
- double free_space_percent = ((1.0 * free_space) / fs_size) * 100;
- if (free_space_percent < kMinimumFreeSpaceThreshold) {
- LOG(ERROR) << "free space " << static_cast<uint64_t>(free_space_percent)
- << "% is below the minimum threshold of " << kMinimumFreeSpaceThreshold << "%";
- return INSTALL_ERROR_FILE_SYSTEM_CLUTTERED;
- }
- return INSTALL_OK;
-}
-
-int GsiService::PreallocateFiles() {
- if (wipe_userdata_) {
- SplitFiemap::RemoveSplitFiles(userdata_gsi_path_);
- }
- SplitFiemap::RemoveSplitFiles(system_gsi_path_);
-
- // TODO: trigger GC from fiemap writer.
-
- // Create fallocated files.
- if (int status = PreallocateUserdata()) {
- return status;
- }
- if (int status = PreallocateSystem()) {
- return status;
- }
-
- // Save the extent information in liblp.
- metadata_ = CreateMetadata();
- if (!metadata_) {
- return INSTALL_ERROR_GENERIC;
- }
-
- UpdateProgress(STATUS_COMPLETE, 0);
- return INSTALL_OK;
-}
-
-int GsiService::PreallocateUserdata() {
- int error;
- std::unique_ptr<SplitFiemap> userdata_image;
- if (wipe_userdata_ || access(userdata_gsi_path_.c_str(), F_OK)) {
- StartAsyncOperation("create userdata", userdata_size_);
- userdata_image = CreateFiemapWriter(userdata_gsi_path_, userdata_size_, &error);
- if (!userdata_image) {
- LOG(ERROR) << "Could not create userdata image: " << userdata_gsi_path_;
- return error;
- }
- // Signal that we need to reformat userdata.
- wipe_userdata_ = true;
- } else {
- userdata_image = CreateFiemapWriter(userdata_gsi_path_, 0, &error);
- if (!userdata_image) {
- LOG(ERROR) << "Could not open userdata image: " << userdata_gsi_path_;
- return error;
- }
- if (userdata_size_ && userdata_image->size() < userdata_size_) {
- // :TODO: need to fallocate more blocks and resizefs.
- }
- userdata_size_ = userdata_image->size();
- }
-
- userdata_block_size_ = userdata_image->block_size();
-
- Image image = {
- .writer = std::move(userdata_image),
- .actual_size = userdata_size_,
- };
- partitions_.emplace(std::make_pair("userdata_gsi", std::move(image)));
- return INSTALL_OK;
-}
-
-int GsiService::PreallocateSystem() {
- StartAsyncOperation("create system", gsi_size_);
-
- int error;
- auto system_image = CreateFiemapWriter(system_gsi_path_, gsi_size_, &error);
- if (!system_image) {
- return error;
- }
-
- system_block_size_ = system_image->block_size();
-
- Image image = {
- .writer = std::move(system_image),
- .actual_size = gsi_size_,
- };
- partitions_.emplace(std::make_pair("system_gsi", std::move(image)));
- return INSTALL_OK;
-}
-
-std::unique_ptr<SplitFiemap> GsiService::CreateFiemapWriter(const std::string& path, uint64_t size,
- int* error) {
- bool create = (size != 0);
-
- std::function<bool(uint64_t, uint64_t)> progress;
- if (create) {
- // 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;
- };
- }
-
- std::unique_ptr<SplitFiemap> file;
- if (!size) {
- file = SplitFiemap::Open(path);
- } else {
- file = SplitFiemap::Create(path, size, 0, std::move(progress));
- }
- if (!file) {
- LOG(ERROR) << "failed to create or open " << path;
- *error = INSTALL_ERROR_GENERIC;
- return nullptr;
- }
-
- uint64_t extents = file->extents().size();
- if (extents > kMaximumExtents) {
- LOG(ERROR) << "file " << path << " has too many extents: " << extents;
- *error = INSTALL_ERROR_FILE_SYSTEM_CLUTTERED;
- return nullptr;
- }
- return file;
-}
-
-// Write data through an fd.
-class FdWriter final : public GsiService::WriteHelper {
- public:
- FdWriter(const std::string& path, unique_fd&& fd) : path_(path), fd_(std::move(fd)) {}
-
- bool Write(const void* data, uint64_t bytes) override {
- return android::base::WriteFully(fd_, data, bytes);
- }
- bool Flush() override {
- if (fsync(fd_)) {
- PLOG(ERROR) << "fsync failed: " << path_;
- return false;
- }
- return true;
- }
-
- private:
- std::string path_;
- unique_fd fd_;
-};
-
-// Write data through a SplitFiemap.
-class SplitFiemapWriter final : public GsiService::WriteHelper {
- public:
- explicit SplitFiemapWriter(SplitFiemap* writer) : writer_(writer) {}
-
- bool Write(const void* data, uint64_t bytes) override { return writer_->Write(data, bytes); }
- bool Flush() override { return writer_->Flush(); }
-
- private:
- SplitFiemap* writer_;
-};
-
-std::unique_ptr<GsiService::WriteHelper> GsiService::OpenPartition(const std::string& name) {
- if (can_use_devicemapper_) {
- std::string path;
- if (!CreateLogicalPartition(kUserdataDevice, *metadata_.get(), name, true, kDmTimeout,
- &path)) {
- LOG(ERROR) << "Error creating device-mapper node for " << name;
- return {};
- }
-
- static const int kOpenFlags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
- unique_fd fd(open(path.c_str(), kOpenFlags));
- if (fd < 0) {
- PLOG(ERROR) << "could not open " << path;
- }
- return std::make_unique<FdWriter>(GetImagePath(install_dir_, name), std::move(fd));
- }
-
- auto iter = partitions_.find(name);
- if (iter == partitions_.end()) {
- LOG(ERROR) << "could not find partition " << name;
- return {};
- }
- return std::make_unique<SplitFiemapWriter>(iter->second.writer.get());
-}
-
-bool GsiService::CommitGsiChunk(int stream_fd, int64_t bytes) {
- StartAsyncOperation("write gsi", gsi_size_);
-
- if (bytes < 0) {
- LOG(ERROR) << "chunk size " << bytes << " is negative";
- return false;
- }
-
- auto buffer = std::make_unique<char[]>(system_block_size_);
-
- int progress = -1;
- uint64_t remaining = bytes;
- while (remaining) {
- // :TODO: check file pin status!
- size_t max_to_read = std::min(system_block_size_, remaining);
- ssize_t rv = TEMP_FAILURE_RETRY(read(stream_fd, buffer.get(), max_to_read));
- if (rv < 0) {
- PLOG(ERROR) << "read gsi chunk";
- return false;
- }
- if (rv == 0) {
- LOG(ERROR) << "no bytes left in stream";
- return false;
- }
- if (!CommitGsiChunk(buffer.get(), rv)) {
- return false;
- }
- CHECK(static_cast<uint64_t>(rv) <= remaining);
- remaining -= rv;
-
- // Only update the progress when the % (or permille, in this case)
- // significantly changes.
- int new_progress = ((gsi_size_ - remaining) * 1000) / gsi_size_;
- if (new_progress != progress) {
- UpdateProgress(STATUS_WORKING, gsi_size_ - remaining);
- }
- }
-
- UpdateProgress(STATUS_COMPLETE, gsi_size_);
- return true;
-}
-
-bool GsiService::CommitGsiChunk(const void* data, size_t bytes) {
- if (!installing_) {
- LOG(ERROR) << "no gsi installation in progress";
- return false;
- }
- if (static_cast<uint64_t>(bytes) > gsi_size_ - gsi_bytes_written_) {
- // We cannot write past the end of the image file.
- LOG(ERROR) << "chunk size " << bytes << " exceeds remaining image size (" << gsi_size_
- << " expected, " << gsi_bytes_written_ << " written)";
- return false;
- }
-
- if (!system_writer_->Write(data, bytes)) {
- PLOG(ERROR) << "write failed";
- return false;
- }
- gsi_bytes_written_ += bytes;
- return true;
-}
-
-int GsiService::SetGsiBootable(bool one_shot) {
- if (gsi_bytes_written_ != gsi_size_) {
- // We cannot boot if the image is incomplete.
- LOG(ERROR) << "image incomplete; expected " << gsi_size_ << " bytes, waiting for "
- << (gsi_size_ - gsi_bytes_written_) << " bytes";
- return INSTALL_ERROR_GENERIC;
- }
-
- if (!system_writer_->Flush()) {
- return INSTALL_ERROR_GENERIC;
- }
-
- // If files moved (are no longer pinned), the metadata file will be invalid.
- for (const auto& [name, image] : partitions_) {
- if (!image.writer->HasPinnedExtents()) {
- LOG(ERROR) << name << " no longer has pinned extents";
- return INSTALL_ERROR_GENERIC;
- }
- }
-
- // Remember the installation directory.
- if (!android::base::WriteStringToFile(install_dir_, kGsiInstallDirFile)) {
- PLOG(ERROR) << "write failed: " << kGsiInstallDirFile;
- return INSTALL_ERROR_GENERIC;
- }
-
- // Note: create the install status file last, since this is the actual boot
- // indicator.
- if (!CreateMetadataFile() || !SetBootMode(one_shot) || !CreateInstallStatusFile()) {
- return INSTALL_ERROR_GENERIC;
- }
- return INSTALL_OK;
-}
-
int GsiService::ReenableGsi(bool one_shot) {
if (!android::gsi::IsGsiInstalled()) {
LOG(ERROR) << "no gsi installed - cannot re-enable";
@@ -880,95 +473,8 @@
return INSTALL_ERROR_GENERIC;
}
- if (IsGsiRunning()) {
- if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
- return INSTALL_ERROR_GENERIC;
- }
- return INSTALL_OK;
- }
- // Note: this metadata is only used to recover the original partition sizes.
- // We do not trust the extent information, which will get rebuilt later.
- auto old_metadata = ReadFromImageFile(kGsiLpMetadataFile);
- if (!old_metadata) {
- LOG(ERROR) << "GSI install is incomplete";
- return INSTALL_ERROR_GENERIC;
- }
-
- // Set up enough installer state so that we can use various helper
- // methods.
- //
- // TODO(dvander) Extract all of the installer state into a separate
- // class so this is more manageable.
- install_dir_ = GetInstalledImageDir();
- system_gsi_path_ = GetImagePath(install_dir_, "system_gsi");
- if (int error = DetermineReadWriteMethod()) {
- return error;
- }
-
- // Recover parition information.
- Image userdata_image;
- if (int error = GetExistingImage(*old_metadata.get(), "userdata_gsi", &userdata_image)) {
- return error;
- }
- partitions_.emplace(std::make_pair("userdata_gsi", std::move(userdata_image)));
-
- Image system_image;
- if (int error = GetExistingImage(*old_metadata.get(), "system_gsi", &system_image)) {
- return error;
- }
- partitions_.emplace(std::make_pair("system_gsi", std::move(system_image)));
-
- metadata_ = CreateMetadata();
- if (!metadata_) {
- return INSTALL_ERROR_GENERIC;
- }
- if (!CreateMetadataFile() || !SetBootMode(one_shot) || !CreateInstallStatusFile()) {
- return INSTALL_ERROR_GENERIC;
- }
- return INSTALL_OK;
-}
-
-static uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition) {
- uint64_t total = 0;
- for (size_t i = 0; i < partition.num_extents; i++) {
- const auto& extent = metadata.extents[partition.first_extent_index + i];
- if (extent.target_type != LP_TARGET_TYPE_LINEAR) {
- LOG(ERROR) << "non-linear extent detected";
- return 0;
- }
- total += extent.num_sectors * LP_SECTOR_SIZE;
- }
- return total;
-}
-
-static uint64_t GetPartitionSize(const LpMetadata& metadata, const std::string& name) {
- for (const auto& partition : metadata.partitions) {
- if (GetPartitionName(partition) == name) {
- return GetPartitionSize(metadata, partition);
- }
- }
- return 0;
-}
-
-int GsiService::GetExistingImage(const LpMetadata& metadata, const std::string& name,
- Image* image) {
- int error;
- std::string path = GetInstalledImagePath(name);
- auto writer = CreateFiemapWriter(path.c_str(), 0, &error);
- if (!writer) {
- return error;
- }
-
- // Even after recovering the FIEMAP, we also need to know the exact intended
- // size of the image, since FiemapWriter may have extended the final block.
- uint64_t actual_size = GetPartitionSize(metadata, name);
- if (!actual_size) {
- LOG(ERROR) << "Could not determine the pre-existing size of " << name;
- return INSTALL_ERROR_GENERIC;
- }
- image->writer = std::move(writer);
- image->actual_size = actual_size;
- return INSTALL_OK;
+ installer_ = std::make_unique<GsiInstaller>(this, GetInstalledImageDir());
+ return installer_->ReenableGsi(one_shot);
}
bool GsiService::RemoveGsiFiles(const std::string& install_dir, bool wipeUserdata) {
@@ -1004,7 +510,7 @@
LOG(ERROR) << "cannot disable gsi install - no install detected";
return false;
}
- if (installing_) {
+ if (installer_) {
LOG(ERROR) << "cannot disable gsi during GSI installation";
return false;
}
@@ -1015,135 +521,6 @@
return true;
}
-std::unique_ptr<LpMetadata> GsiService::CreateMetadata() {
- std::string data_device_path;
- if (install_dir_ == kGsiDataFolder && !access(kUserdataDevice, F_OK)) {
- data_device_path = kUserdataDevice;
- } else {
- auto writer = partitions_["system_gsi"].writer.get();
- data_device_path = writer->bdev_path();
- }
- auto data_device_name = android::base::Basename(data_device_path);
-
- PartitionOpener opener;
- BlockDeviceInfo data_device_info;
- if (!opener.GetInfo(data_device_path, &data_device_info)) {
- LOG(ERROR) << "Error reading userdata partition";
- return nullptr;
- }
-
- std::vector<BlockDeviceInfo> block_devices = {data_device_info};
- auto builder = MetadataBuilder::New(block_devices, data_device_name, 128 * 1024, 1);
- if (!builder) {
- LOG(ERROR) << "Error creating metadata builder";
- return nullptr;
- }
- builder->IgnoreSlotSuffixing();
-
- for (const auto& [name, image] : partitions_) {
- uint32_t flags = LP_PARTITION_ATTR_NONE;
- if (name == "system_gsi") {
- flags |= LP_PARTITION_ATTR_READONLY;
- }
- Partition* partition = builder->AddPartition(name, flags);
- if (!partition) {
- LOG(ERROR) << "Error adding " << name << " to partition table";
- return nullptr;
- }
- if (!AddPartitionFiemap(builder.get(), partition, image, data_device_name)) {
- return nullptr;
- }
- }
-
- auto metadata = builder->Export();
- if (!metadata) {
- LOG(ERROR) << "Error exporting partition table";
- return nullptr;
- }
- return metadata;
-}
-
-bool GsiService::CreateMetadataFile() {
- if (!WriteToImageFile(kGsiLpMetadataFile, *metadata_.get())) {
- LOG(ERROR) << "Error writing GSI partition table image";
- return false;
- }
- return true;
-}
-
-bool GsiService::FormatUserdata() {
- auto writer = OpenPartition("userdata_gsi");
- if (!writer) {
- return false;
- }
-
- // libcutils checks the first 4K, no matter the block size.
- std::string zeroes(4096, 0);
- if (!writer->Write(zeroes.data(), zeroes.size())) {
- PLOG(ERROR) << "write userdata_gsi";
- return false;
- }
- return true;
-}
-
-bool GsiService::AddPartitionFiemap(MetadataBuilder* builder, Partition* partition,
- const Image& image, const std::string& block_device) {
- uint64_t sectors_needed = image.actual_size / LP_SECTOR_SIZE;
- for (const auto& extent : image.writer->extents()) {
- // :TODO: block size check for length, not sector size
- if (extent.fe_length % LP_SECTOR_SIZE != 0) {
- LOG(ERROR) << "Extent is not sector-aligned: " << extent.fe_length;
- return false;
- }
- if (extent.fe_physical % LP_SECTOR_SIZE != 0) {
- LOG(ERROR) << "Extent physical sector is not sector-aligned: " << extent.fe_physical;
- return false;
- }
-
- uint64_t num_sectors =
- std::min(static_cast<uint64_t>(extent.fe_length / LP_SECTOR_SIZE), sectors_needed);
- if (!num_sectors || !sectors_needed) {
- // This should never happen, but we include it just in case. It would
- // indicate that the last filesystem block had multiple extents.
- LOG(WARNING) << "FiemapWriter allocated extra blocks";
- break;
- }
-
- uint64_t physical_sector = extent.fe_physical / LP_SECTOR_SIZE;
- if (!builder->AddLinearExtent(partition, block_device, num_sectors, physical_sector)) {
- LOG(ERROR) << "Could not add extent to lp metadata";
- return false;
- }
-
- sectors_needed -= num_sectors;
- }
- return true;
-}
-
-bool GsiService::SetBootMode(bool one_shot) {
- if (one_shot) {
- if (!android::base::WriteStringToFile("1", kGsiOneShotBootFile)) {
- PLOG(ERROR) << "write " << kGsiOneShotBootFile;
- return false;
- }
- } else if (!access(kGsiOneShotBootFile, F_OK)) {
- std::string error;
- if (!android::base::RemoveFileIfExists(kGsiOneShotBootFile, &error)) {
- LOG(ERROR) << error;
- return false;
- }
- }
- return true;
-}
-
-bool GsiService::CreateInstallStatusFile() {
- if (!android::base::WriteStringToFile("0", kGsiInstallStatusFile)) {
- PLOG(ERROR) << "write " << kGsiInstallStatusFile;
- return false;
- }
- return true;
-}
-
void GsiService::RunStartupTasks() {
if (!IsGsiInstalled()) {
return;