diff options
-rw-r--r-- | install/adb_install.cpp | 7 | ||||
-rw-r--r-- | install/fuse_install.cpp | 9 | ||||
-rw-r--r-- | install/include/install/fuse_install.h | 2 | ||||
-rw-r--r-- | install/include/install/install.h | 4 | ||||
-rw-r--r-- | install/install.cpp | 51 | ||||
-rw-r--r-- | recovery.cpp | 6 |
6 files changed, 54 insertions, 25 deletions
diff --git a/install/adb_install.cpp b/install/adb_install.cpp index ee79a32c0..5cba7b67c 100644 --- a/install/adb_install.cpp +++ b/install/adb_install.cpp @@ -90,11 +90,12 @@ static bool WriteStatusToFd(MinadbdCommandStatus status, int fd) { // Installs the package from FUSE. Returns the installation result and whether it should continue // waiting for new commands. -static auto AdbInstallPackageHandler(RecoveryUI* ui, InstallResult* result) { +static auto AdbInstallPackageHandler(Device* device, InstallResult* result) { // How long (in seconds) we wait for the package path to be ready. It doesn't need to be too long // because the minadbd service has already issued an install command. FUSE_SIDELOAD_HOST_PATHNAME // will start to exist once the host connects and starts serving a package. Poll for its // appearance. (Note that inotify doesn't work with FUSE.) + auto ui = device->GetUI(); constexpr int ADB_INSTALL_TIMEOUT = 15; bool should_continue = true; *result = INSTALL_ERROR; @@ -114,7 +115,7 @@ static auto AdbInstallPackageHandler(RecoveryUI* ui, InstallResult* result) { 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); + *result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0, device); break; } @@ -348,7 +349,7 @@ InstallResult ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinActi InstallResult install_result = INSTALL_ERROR; std::map<MinadbdCommand, CommandFunction> command_map{ - { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, ui, &install_result) }, + { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, device, &install_result) }, { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid, &install_result, reboot_action) }, { MinadbdCommand::kRebootBootloader, diff --git a/install/fuse_install.cpp b/install/fuse_install.cpp index 143b5d3fb..197e1debb 100644 --- a/install/fuse_install.cpp +++ b/install/fuse_install.cpp @@ -146,10 +146,11 @@ static bool StartInstallPackageFuse(std::string_view path) { return run_fuse_sideload(std::move(fuse_data_provider)) == 0; } -InstallResult InstallWithFuseFromPath(std::string_view path, RecoveryUI* ui) { +InstallResult InstallWithFuseFromPath(std::string_view path, Device* device) { // We used to use fuse in a thread as opposed to a process. Since accessing // through fuse involves going from kernel to userspace to kernel, it leads // to deadlock when a page fault occurs. (Bug: 26313124) + auto ui = device->GetUI(); pid_t child; if ((child = fork()) == 0) { bool status = StartInstallPackageFuse(path); @@ -183,8 +184,8 @@ InstallResult InstallWithFuseFromPath(std::string_view path, RecoveryUI* 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); + result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0 /* retry_count */, + device); break; } @@ -226,7 +227,7 @@ InstallResult ApplyFromSdcard(Device* device) { ui->Print("\n-- Install %s ...\n", path.c_str()); SetSdcardUpdateBootloaderMessage(); - auto result = InstallWithFuseFromPath(path, ui); + auto result = InstallWithFuseFromPath(path, device); ensure_path_unmounted(SDCARD_ROOT); return result; } diff --git a/install/include/install/fuse_install.h b/install/include/install/fuse_install.h index 63b116aeb..29c283f40 100644 --- a/install/include/install/fuse_install.h +++ b/install/include/install/fuse_install.h @@ -25,6 +25,6 @@ // Starts FUSE with the package from |path| as the data source. And installs the package from // |FUSE_SIDELOAD_HOST_PATHNAME|. The |path| can point to the location of a package zip file or a // block map file with the prefix '@'; e.g. /sdcard/package.zip, @/cache/recovery/block.map. -InstallResult InstallWithFuseFromPath(std::string_view path, RecoveryUI* ui); +InstallResult InstallWithFuseFromPath(std::string_view path, Device* device); InstallResult ApplyFromSdcard(Device* device); diff --git a/install/include/install/install.h b/install/include/install/install.h index 704841f8e..0f5102f82 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -25,6 +25,7 @@ #include <ziparchive/zip_archive.h> #include "otautil/package.h" +#include "recovery_ui/device.h" #include "recovery_ui/ui.h" enum InstallResult { @@ -49,7 +50,8 @@ enum class OtaType { // 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); + bool should_wipe_cache, int retry_count, + Device* ui); // Verifies the package by ota keys. Returns true if the package is verified successfully, // otherwise returns false. diff --git a/install/install.cpp b/install/install.cpp index bb8c3b825..811bcb021 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -235,30 +235,41 @@ bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, Ot return true; } -bool SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd, - std::vector<std::string>* cmd) { - CHECK(cmd != nullptr); - +static std::string ExtractPayloadProperties(ZipArchiveHandle zip) { // For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset // in the zip file. static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt"; ZipEntry64 properties_entry; if (FindEntry(zip, AB_OTA_PAYLOAD_PROPERTIES, &properties_entry) != 0) { LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD_PROPERTIES; - return false; + return {}; } auto properties_entry_length = properties_entry.uncompressed_length; if (properties_entry_length > std::numeric_limits<size_t>::max()) { LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES << " because's uncompressed size exceeds size of address space. " << properties_entry_length; - return false; + return {}; } - std::vector<uint8_t> payload_properties(properties_entry_length); + std::string payload_properties(properties_entry_length, '\0'); int32_t err = - ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length); + ExtractToMemory(zip, &properties_entry, reinterpret_cast<uint8_t*>(payload_properties.data()), + properties_entry_length); if (err != 0) { LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES << ": " << ErrorCodeString(err); + return {}; + } + return payload_properties; +} + +bool SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd, + std::vector<std::string>* cmd) { + CHECK(cmd != nullptr); + + // For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset + // in the zip file. + const auto payload_properties = ExtractPayloadProperties(zip); + if (payload_properties.empty()) { return false; } @@ -332,10 +343,20 @@ static void log_max_temperature(int* max_temperature, const std::atomic<bool>& l } } +static bool PerformPowerwashIfRequired(ZipArchiveHandle zip, Device *device) { + const auto payload_properties = ExtractPayloadProperties(zip); + if (payload_properties.find("POWERWASH=1") != std::string::npos) { + LOG(INFO) << "Payload properties has POWERWASH=1, wiping userdata..."; + return WipeData(device, true); + } + return true; +} + // If the package contains an update binary, extract it and run it. static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, std::vector<std::string>* log_buffer, int retry_count, - int* max_temperature, RecoveryUI* ui) { + int* max_temperature, Device* device) { + auto ui = device->GetUI(); std::map<std::string, std::string> metadata; auto zip = package->GetZipArchiveHandle(); if (!ReadMetadataFromPackage(zip, &metadata)) { @@ -530,13 +551,15 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, } else { LOG(FATAL) << "Invalid status code " << status; } + PerformPowerwashIfRequired(zip, device); return INSTALL_SUCCESS; } static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache, std::vector<std::string>* log_buffer, int retry_count, - int* max_temperature, RecoveryUI* ui) { + int* max_temperature, Device* device) { + auto ui = device->GetUI(); ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); // Give verification half the progress bar... ui->SetProgressType(RecoveryUI::DETERMINATE); @@ -554,7 +577,8 @@ static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache, ui->Print("Retry attempt: %d\n", retry_count); } ui->SetEnableReboot(false); - auto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui); + auto result = + TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, device); ui->SetEnableReboot(true); ui->Print("\n"); @@ -562,7 +586,8 @@ static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache, } InstallResult InstallPackage(Package* package, const std::string_view package_id, - bool should_wipe_cache, int retry_count, RecoveryUI* ui) { + bool should_wipe_cache, int retry_count, Device* device) { + auto ui = device->GetUI(); auto start = std::chrono::system_clock::now(); int start_temperature = GetMaxValueFromThermalZone(); @@ -584,7 +609,7 @@ InstallResult InstallPackage(Package* package, const std::string_view package_id } else { bool updater_wipe_cache = false; result = VerifyAndInstallPackage(package, &updater_wipe_cache, &log_buffer, retry_count, - &max_temperature, ui); + &max_temperature, device); should_wipe_cache = should_wipe_cache || updater_wipe_cache; } diff --git a/recovery.cpp b/recovery.cpp index 641fe4788..0c977c361 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -752,20 +752,20 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri status = INSTALL_ERROR; } else if (install_with_fuse || should_use_fuse) { LOG(INFO) << "Installing package " << update_package << " with fuse"; - status = InstallWithFuseFromPath(update_package, ui); + status = InstallWithFuseFromPath(update_package, device); } else if (auto memory_package = Package::CreateMemoryPackage( update_package, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1)); memory_package != nullptr) { status = InstallPackage(memory_package.get(), update_package, should_wipe_cache, - retry_count, ui); + retry_count, device); } else { // We may fail to memory map the package on 32 bit builds for packages with 2GiB+ size. // In such cases, we will try to install the package with fuse. This is not the default // installation method because it introduces a layer of indirection from the kernel space. LOG(WARNING) << "Failed to memory map package " << update_package << "; falling back to install with fuse"; - status = InstallWithFuseFromPath(update_package, ui); + status = InstallWithFuseFromPath(update_package, device); } if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); |