diff options
-rw-r--r-- | install/adb_install.cpp | 6 | ||||
-rw-r--r-- | install/fuse_sdcard_install.cpp | 7 | ||||
-rw-r--r-- | install/include/install/install.h | 11 | ||||
-rw-r--r-- | install/include/install/package.h | 9 | ||||
-rw-r--r-- | install/install.cpp | 75 | ||||
-rw-r--r-- | install/package.cpp | 18 | ||||
-rw-r--r-- | recovery.cpp | 10 |
7 files changed, 83 insertions, 53 deletions
diff --git a/install/adb_install.cpp b/install/adb_install.cpp index 2de1075d2..37280a34c 100644 --- a/install/adb_install.cpp +++ b/install/adb_install.cpp @@ -110,7 +110,11 @@ static auto AdbInstallPackageHandler(RecoveryUI* ui, InstallResult* result) { break; } } - *result = InstallPackage(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, ui); + + auto package = + Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME, + std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); + *result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0, ui); break; } diff --git a/install/fuse_sdcard_install.cpp b/install/fuse_sdcard_install.cpp index a5caa6e75..9fdb2f341 100644 --- a/install/fuse_sdcard_install.cpp +++ b/install/fuse_sdcard_install.cpp @@ -182,8 +182,11 @@ InstallResult ApplyFromSdcard(Device* device, RecoveryUI* ui) { break; } } - - result = InstallPackage(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /* retry_count */, ui); + auto package = + Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME, + std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); + result = + InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0 /* retry_count */, ui); break; } diff --git a/install/include/install/install.h b/install/include/install/install.h index 44a5cde91..b4b3a9149 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -44,11 +44,12 @@ enum class OtaType { BRICK, }; -// Installs the given update package. This function should also wipe the cache partition after a -// successful installation if |should_wipe_cache| is true or an updater command asks to wipe the -// cache. -InstallResult InstallPackage(const std::string& package, bool should_wipe_cache, bool needs_mount, - int retry_count, RecoveryUI* ui); +// Installs the given update package. The package_id is a string provided by the caller (e.g. the +// package path) to identify the package and log to last_install. This function should also wipe the +// cache partition after a successful installation if |should_wipe_cache| is true or an updater +// command asks to wipe the cache. +InstallResult InstallPackage(Package* package, const std::string_view package_id, + bool should_wipe_cache, int retry_count, RecoveryUI* ui); // Verifies the package by ota keys. Returns true if the package is verified successfully, // otherwise returns false. diff --git a/install/include/install/package.h b/install/include/install/package.h index cd44d10be..0b4233238 100644 --- a/install/include/install/package.h +++ b/install/include/install/package.h @@ -28,6 +28,11 @@ #include "verifier.h" +enum class PackageType { + kMemory, + kFile, +}; + // This class serves as a wrapper for an OTA update package. It aims to provide the common // interface for both packages loaded in memory and packages read from fd. class Package : public VerifierInterface { @@ -41,6 +46,10 @@ class Package : public VerifierInterface { virtual ~Package() = default; + virtual PackageType GetType() const = 0; + + virtual std::string GetPath() const = 0; + // Opens the package as a zip file and returns the ZipArchiveHandle. virtual ZipArchiveHandle GetZipArchiveHandle() = 0; diff --git a/install/install.cpp b/install/install.cpp index 445f3ab34..09b88392a 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -320,16 +320,21 @@ static void log_max_temperature(int* max_temperature, const std::atomic<bool>& l } // If the package contains an update binary, extract it and run it. -static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandle zip, - bool* wipe_cache, std::vector<std::string>* log_buffer, - int retry_count, int* max_temperature, RecoveryUI* ui) { +static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, + std::vector<std::string>* log_buffer, int retry_count, + int* max_temperature, RecoveryUI* ui) { std::map<std::string, std::string> metadata; + auto zip = package->GetZipArchiveHandle(); if (!ReadMetadataFromPackage(zip, &metadata)) { LOG(ERROR) << "Failed to parse metadata in the zip file"; return INSTALL_CORRUPT; } bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false); + if (is_ab) { + CHECK(package->GetType() == PackageType::kFile); + } + // Verify against the metadata in the package first. if (is_ab && !CheckPackageMetadata(metadata, OtaType::AB)) { log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure)); @@ -379,10 +384,12 @@ static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandl // updater requests logging the string (e.g. cause of the failure). // + std::string package_path = package->GetPath(); + std::vector<std::string> args; if (auto setup_result = - is_ab ? SetUpAbUpdateCommands(package, zip, pipe_write.get(), &args) - : SetUpNonAbUpdateCommands(package, zip, retry_count, pipe_write.get(), &args); + is_ab ? SetUpAbUpdateCommands(package_path, zip, pipe_write.get(), &args) + : SetUpNonAbUpdateCommands(package_path, zip, retry_count, pipe_write.get(), &args); !setup_result) { log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure)); return INSTALL_CORRUPT; @@ -484,11 +491,11 @@ static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandl } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != EXIT_SUCCESS) { - LOG(ERROR) << "Error in " << package << " (status " << WEXITSTATUS(status) << ")"; + LOG(ERROR) << "Error in " << package_path << " (status " << WEXITSTATUS(status) << ")"; return INSTALL_ERROR; } } else if (WIFSIGNALED(status)) { - LOG(ERROR) << "Error in " << package << " (killed by signal " << WTERMSIG(status) << ")"; + LOG(ERROR) << "Error in " << package_path << " (killed by signal " << WTERMSIG(status) << ")"; return INSTALL_ERROR; } else { LOG(FATAL) << "Invalid status code " << status; @@ -497,7 +504,7 @@ static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandl return INSTALL_SUCCESS; } -// Verifes the compatibility info in a Treble-compatible package. Returns true directly if the +// Verifies the compatibility info in a Treble-compatible package. Returns true directly if the // entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA // package. bool verify_package_compatibility(ZipArchiveHandle package_zip) { @@ -564,37 +571,16 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip) { return false; } -static InstallResult VerifyAndInstallPackage(const std::string& path, bool* wipe_cache, - bool needs_mount, std::vector<std::string>* log_buffer, - int retry_count, int* max_temperature, - RecoveryUI* ui) { +static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache, + std::vector<std::string>* log_buffer, int retry_count, + int* max_temperature, RecoveryUI* ui) { ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); - ui->Print("Finding update package...\n"); // Give verification half the progress bar... ui->SetProgressType(RecoveryUI::DETERMINATE); ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); - LOG(INFO) << "Update location: " << path; - - // Map the update package into memory. - ui->Print("Opening update package...\n"); - - if (needs_mount) { - if (path[0] == '@') { - ensure_path_mounted(path.substr(1)); - } else { - ensure_path_mounted(path); - } - } - - auto package = Package::CreateMemoryPackage( - path, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); - if (!package) { - log_buffer->push_back(android::base::StringPrintf("error: %d", kMapFileFailure)); - return INSTALL_CORRUPT; - } // Verify package. - if (!verify_package(package.get(), ui)) { + if (!verify_package(package, ui)) { log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure)); return INSTALL_CORRUPT; } @@ -618,18 +604,15 @@ static InstallResult VerifyAndInstallPackage(const std::string& path, bool* wipe ui->Print("Retry attempt: %d\n", retry_count); } ui->SetEnableReboot(false); - auto result = - TryUpdateBinary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui); + auto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui); ui->SetEnableReboot(true); ui->Print("\n"); return result; } -InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bool needs_mount, - int retry_count, RecoveryUI* ui) { - CHECK(!path.empty()); - +InstallResult InstallPackage(Package* package, const std::string_view package_id, + bool should_wipe_cache, int retry_count, RecoveryUI* ui) { auto start = std::chrono::system_clock::now(); int start_temperature = GetMaxValueFromThermalZone(); @@ -637,13 +620,19 @@ InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bo InstallResult result; std::vector<std::string> log_buffer; - if (setup_install_mounts() != 0) { + + ui->Print("Finding update package...\n"); + LOG(INFO) << "Update package id: " << package_id; + if (!package) { + log_buffer.push_back(android::base::StringPrintf("error: %d", kMapFileFailure)); + result = INSTALL_CORRUPT; + } else if (setup_install_mounts() != 0) { LOG(ERROR) << "failed to set up expected mounts for install; aborting"; result = INSTALL_ERROR; } else { bool updater_wipe_cache = false; - result = VerifyAndInstallPackage(path, &updater_wipe_cache, needs_mount, &log_buffer, - retry_count, &max_temperature, ui); + result = VerifyAndInstallPackage(package, &updater_wipe_cache, &log_buffer, retry_count, + &max_temperature, ui); should_wipe_cache = should_wipe_cache || updater_wipe_cache; } @@ -671,7 +660,7 @@ InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bo // The first two lines need to be the package name and install result. std::vector<std::string> log_header = { - path, + std::string(package_id), result == INSTALL_SUCCESS ? "1" : "0", "time_total: " + std::to_string(time_total), "retry: " + std::to_string(retry_count), diff --git a/install/package.cpp b/install/package.cpp index 4402f4855..86fc0647d 100644 --- a/install/package.cpp +++ b/install/package.cpp @@ -40,12 +40,20 @@ class MemoryPackage : public Package { ~MemoryPackage() override; + PackageType GetType() const override { + return PackageType::kMemory; + } + // Memory maps the package file if necessary. Initializes the start address and size of the // package. uint64_t GetPackageSize() const override { return package_size_; } + std::string GetPath() const override { + return path_; + } + bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override; ZipArchiveHandle GetZipArchiveHandle() override; @@ -82,10 +90,18 @@ class FilePackage : public Package { ~FilePackage() override; + PackageType GetType() const override { + return PackageType::kFile; + } + uint64_t GetPackageSize() const override { return package_size_; } + std::string GetPath() const override { + return path_; + } + bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override; ZipArchiveHandle GetZipArchiveHandle() override; @@ -253,7 +269,7 @@ ZipArchiveHandle FilePackage::GetZipArchiveHandle() { return zip_handle_; } - if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) { + if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_, false); err != 0) { LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err); return nullptr; } diff --git a/recovery.cpp b/recovery.cpp index eb0c2b216..db66ea7e9 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -732,7 +732,15 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri set_retry_bootloader_message(retry_count + 1, args); } - status = InstallPackage(update_package, should_wipe_cache, true, retry_count, ui); + if (update_package[0] == '@') { + ensure_path_mounted(update_package + 1); + } else { + ensure_path_mounted(update_package); + } + // TODO(xunchang) install package from fuse for large packages on ILP32 builds. + auto package = Package::CreateMemoryPackage( + update_package, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); + status = InstallPackage(package.get(), update_package, should_wipe_cache, retry_count, ui); if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); |