Merge "InstallPackage now takes a package as parameter" am: 87e2275970 am: a927a16841
am: f7498516ca
Change-Id: I904eb7a84395e676f5ec4bddcdc393949524774f
This commit is contained in:
@@ -110,7 +110,11 @@ static auto AdbInstallPackageHandler(RecoveryUI* ui, InstallResult* result) {
|
|||||||
break;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,8 +182,11 @@ InstallResult ApplyFromSdcard(Device* device, RecoveryUI* ui) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto package =
|
||||||
result = InstallPackage(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /* retry_count */, ui);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ enum class OtaType {
|
|||||||
BRICK,
|
BRICK,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Installs the given update package. This function should also wipe the cache partition after a
|
// Installs the given update package. The package_id is a string provided by the caller (e.g. the
|
||||||
// successful installation if |should_wipe_cache| is true or an updater command asks to wipe the
|
// package path) to identify the package and log to last_install. This function should also wipe the
|
||||||
// cache.
|
// cache partition after a successful installation if |should_wipe_cache| is true or an updater
|
||||||
InstallResult InstallPackage(const std::string& package, bool should_wipe_cache, bool needs_mount,
|
// command asks to wipe the cache.
|
||||||
int retry_count, RecoveryUI* ui);
|
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,
|
// Verifies the package by ota keys. Returns true if the package is verified successfully,
|
||||||
// otherwise returns false.
|
// otherwise returns false.
|
||||||
|
|||||||
@@ -28,6 +28,11 @@
|
|||||||
|
|
||||||
#include "verifier.h"
|
#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
|
// 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.
|
// interface for both packages loaded in memory and packages read from fd.
|
||||||
class Package : public VerifierInterface {
|
class Package : public VerifierInterface {
|
||||||
@@ -41,6 +46,10 @@ class Package : public VerifierInterface {
|
|||||||
|
|
||||||
virtual ~Package() = default;
|
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.
|
// Opens the package as a zip file and returns the ZipArchiveHandle.
|
||||||
virtual ZipArchiveHandle GetZipArchiveHandle() = 0;
|
virtual ZipArchiveHandle GetZipArchiveHandle() = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
// If the package contains an update binary, extract it and run it.
|
||||||
static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandle zip,
|
static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache,
|
||||||
bool* wipe_cache, std::vector<std::string>* log_buffer,
|
std::vector<std::string>* log_buffer, int retry_count,
|
||||||
int retry_count, int* max_temperature, RecoveryUI* ui) {
|
int* max_temperature, RecoveryUI* ui) {
|
||||||
std::map<std::string, std::string> metadata;
|
std::map<std::string, std::string> metadata;
|
||||||
|
auto zip = package->GetZipArchiveHandle();
|
||||||
if (!ReadMetadataFromPackage(zip, &metadata)) {
|
if (!ReadMetadataFromPackage(zip, &metadata)) {
|
||||||
LOG(ERROR) << "Failed to parse metadata in the zip file";
|
LOG(ERROR) << "Failed to parse metadata in the zip file";
|
||||||
return INSTALL_CORRUPT;
|
return INSTALL_CORRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false);
|
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.
|
// Verify against the metadata in the package first.
|
||||||
if (is_ab && !CheckPackageMetadata(metadata, OtaType::AB)) {
|
if (is_ab && !CheckPackageMetadata(metadata, OtaType::AB)) {
|
||||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
|
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).
|
// updater requests logging the string (e.g. cause of the failure).
|
||||||
//
|
//
|
||||||
|
|
||||||
|
std::string package_path = package->GetPath();
|
||||||
|
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
if (auto setup_result =
|
if (auto setup_result =
|
||||||
is_ab ? SetUpAbUpdateCommands(package, zip, pipe_write.get(), &args)
|
is_ab ? SetUpAbUpdateCommands(package_path, zip, pipe_write.get(), &args)
|
||||||
: SetUpNonAbUpdateCommands(package, zip, retry_count, pipe_write.get(), &args);
|
: SetUpNonAbUpdateCommands(package_path, zip, retry_count, pipe_write.get(), &args);
|
||||||
!setup_result) {
|
!setup_result) {
|
||||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
|
log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
|
||||||
return INSTALL_CORRUPT;
|
return INSTALL_CORRUPT;
|
||||||
@@ -484,11 +491,11 @@ static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandl
|
|||||||
}
|
}
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
if (WEXITSTATUS(status) != EXIT_SUCCESS) {
|
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;
|
return INSTALL_ERROR;
|
||||||
}
|
}
|
||||||
} else if (WIFSIGNALED(status)) {
|
} 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;
|
return INSTALL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
LOG(FATAL) << "Invalid status code " << status;
|
LOG(FATAL) << "Invalid status code " << status;
|
||||||
@@ -497,7 +504,7 @@ static InstallResult TryUpdateBinary(const std::string& package, ZipArchiveHandl
|
|||||||
return INSTALL_SUCCESS;
|
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
|
// entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA
|
||||||
// package.
|
// package.
|
||||||
bool verify_package_compatibility(ZipArchiveHandle package_zip) {
|
bool verify_package_compatibility(ZipArchiveHandle package_zip) {
|
||||||
@@ -564,37 +571,16 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static InstallResult VerifyAndInstallPackage(const std::string& path, bool* wipe_cache,
|
static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache,
|
||||||
bool needs_mount, std::vector<std::string>* log_buffer,
|
std::vector<std::string>* log_buffer, int retry_count,
|
||||||
int retry_count, int* max_temperature,
|
int* max_temperature, RecoveryUI* ui) {
|
||||||
RecoveryUI* ui) {
|
|
||||||
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
|
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
|
||||||
ui->Print("Finding update package...\n");
|
|
||||||
// Give verification half the progress bar...
|
// Give verification half the progress bar...
|
||||||
ui->SetProgressType(RecoveryUI::DETERMINATE);
|
ui->SetProgressType(RecoveryUI::DETERMINATE);
|
||||||
ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
|
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.
|
// Verify package.
|
||||||
if (!verify_package(package.get(), ui)) {
|
if (!verify_package(package, ui)) {
|
||||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
|
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
|
||||||
return INSTALL_CORRUPT;
|
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->Print("Retry attempt: %d\n", retry_count);
|
||||||
}
|
}
|
||||||
ui->SetEnableReboot(false);
|
ui->SetEnableReboot(false);
|
||||||
auto result =
|
auto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui);
|
||||||
TryUpdateBinary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui);
|
|
||||||
ui->SetEnableReboot(true);
|
ui->SetEnableReboot(true);
|
||||||
ui->Print("\n");
|
ui->Print("\n");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bool needs_mount,
|
InstallResult InstallPackage(Package* package, const std::string_view package_id,
|
||||||
int retry_count, RecoveryUI* ui) {
|
bool should_wipe_cache, int retry_count, RecoveryUI* ui) {
|
||||||
CHECK(!path.empty());
|
|
||||||
|
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
int start_temperature = GetMaxValueFromThermalZone();
|
int start_temperature = GetMaxValueFromThermalZone();
|
||||||
@@ -637,13 +620,19 @@ InstallResult InstallPackage(const std::string& path, bool should_wipe_cache, bo
|
|||||||
|
|
||||||
InstallResult result;
|
InstallResult result;
|
||||||
std::vector<std::string> log_buffer;
|
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";
|
LOG(ERROR) << "failed to set up expected mounts for install; aborting";
|
||||||
result = INSTALL_ERROR;
|
result = INSTALL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
bool updater_wipe_cache = false;
|
bool updater_wipe_cache = false;
|
||||||
result = VerifyAndInstallPackage(path, &updater_wipe_cache, needs_mount, &log_buffer,
|
result = VerifyAndInstallPackage(package, &updater_wipe_cache, &log_buffer, retry_count,
|
||||||
retry_count, &max_temperature, ui);
|
&max_temperature, ui);
|
||||||
should_wipe_cache = should_wipe_cache || updater_wipe_cache;
|
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.
|
// The first two lines need to be the package name and install result.
|
||||||
std::vector<std::string> log_header = {
|
std::vector<std::string> log_header = {
|
||||||
path,
|
std::string(package_id),
|
||||||
result == INSTALL_SUCCESS ? "1" : "0",
|
result == INSTALL_SUCCESS ? "1" : "0",
|
||||||
"time_total: " + std::to_string(time_total),
|
"time_total: " + std::to_string(time_total),
|
||||||
"retry: " + std::to_string(retry_count),
|
"retry: " + std::to_string(retry_count),
|
||||||
|
|||||||
@@ -40,12 +40,20 @@ class MemoryPackage : public Package {
|
|||||||
|
|
||||||
~MemoryPackage() override;
|
~MemoryPackage() override;
|
||||||
|
|
||||||
|
PackageType GetType() const override {
|
||||||
|
return PackageType::kMemory;
|
||||||
|
}
|
||||||
|
|
||||||
// Memory maps the package file if necessary. Initializes the start address and size of the
|
// Memory maps the package file if necessary. Initializes the start address and size of the
|
||||||
// package.
|
// package.
|
||||||
uint64_t GetPackageSize() const override {
|
uint64_t GetPackageSize() const override {
|
||||||
return package_size_;
|
return package_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetPath() const override {
|
||||||
|
return path_;
|
||||||
|
}
|
||||||
|
|
||||||
bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
|
bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
|
||||||
|
|
||||||
ZipArchiveHandle GetZipArchiveHandle() override;
|
ZipArchiveHandle GetZipArchiveHandle() override;
|
||||||
@@ -82,10 +90,18 @@ class FilePackage : public Package {
|
|||||||
|
|
||||||
~FilePackage() override;
|
~FilePackage() override;
|
||||||
|
|
||||||
|
PackageType GetType() const override {
|
||||||
|
return PackageType::kFile;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GetPackageSize() const override {
|
uint64_t GetPackageSize() const override {
|
||||||
return package_size_;
|
return package_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetPath() const override {
|
||||||
|
return path_;
|
||||||
|
}
|
||||||
|
|
||||||
bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
|
bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
|
||||||
|
|
||||||
ZipArchiveHandle GetZipArchiveHandle() override;
|
ZipArchiveHandle GetZipArchiveHandle() override;
|
||||||
@@ -253,7 +269,7 @@ ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
|
|||||||
return zip_handle_;
|
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);
|
LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
10
recovery.cpp
10
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);
|
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) {
|
if (status != INSTALL_SUCCESS) {
|
||||||
ui->Print("Installation aborted.\n");
|
ui->Print("Installation aborted.\n");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user