Refactor the code to check the metadata
The two functions check_wipe_package() and check_newer_ab_build() were using the same flow; and checked the same device properties against the metadata file in the package. These properties include: ota_type, pre-device, and serial number. Therefore, we can consolidate the checks to a single function; and continue to check the fingerprint and timestamp only for AB updates. This change also addresses the need to accept multiple serial number in the wipe package. Bug: 118401208 Test: unit tests pass Change-Id: Ia6bc48fb6effcae059a2ff2cf71764b4136b4c00
This commit is contained in:
parent
d84d570d8c
commit
93b5bf261c
4 changed files with 415 additions and 152 deletions
234
install.cpp
234
install.cpp
|
@ -32,9 +32,7 @@
|
|||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
@ -47,7 +45,6 @@
|
|||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <vintf/VintfObjectRecovery.h>
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "otautil/error_code.h"
|
||||
|
@ -67,18 +64,7 @@ static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
|
|||
|
||||
static std::condition_variable finish_log_temperature;
|
||||
|
||||
// This function parses and returns the build.version.incremental
|
||||
static std::string parse_build_number(const std::string& str) {
|
||||
size_t pos = str.find('=');
|
||||
if (pos != std::string::npos) {
|
||||
return android::base::Trim(str.substr(pos+1));
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Failed to parse build number in " << str;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool read_metadata_from_package(ZipArchiveHandle zip, std::string* metadata) {
|
||||
bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::string>* metadata) {
|
||||
CHECK(metadata != nullptr);
|
||||
|
||||
static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
|
||||
|
@ -90,101 +76,79 @@ bool read_metadata_from_package(ZipArchiveHandle zip, std::string* metadata) {
|
|||
}
|
||||
|
||||
uint32_t length = entry.uncompressed_length;
|
||||
metadata->resize(length, '\0');
|
||||
int32_t err = ExtractToMemory(zip, &entry, reinterpret_cast<uint8_t*>(&(*metadata)[0]), length);
|
||||
std::string metadata_string(length, '\0');
|
||||
int32_t err =
|
||||
ExtractToMemory(zip, &entry, reinterpret_cast<uint8_t*>(&metadata_string[0]), length);
|
||||
if (err != 0) {
|
||||
LOG(ERROR) << "Failed to extract " << METADATA_PATH << ": " << ErrorCodeString(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const std::string& line : android::base::Split(metadata_string, "\n")) {
|
||||
size_t eq = line.find('=');
|
||||
if (eq != std::string::npos) {
|
||||
metadata->emplace(android::base::Trim(line.substr(0, eq)),
|
||||
android::base::Trim(line.substr(eq + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
|
||||
static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::string>* log_buffer) {
|
||||
std::string metadata;
|
||||
if (!read_metadata_from_package(zip, &metadata)) {
|
||||
return;
|
||||
}
|
||||
// Examples of the pre-build and post-build strings in metadata:
|
||||
// pre-build-incremental=2943039
|
||||
// post-build-incremental=2951741
|
||||
std::vector<std::string> lines = android::base::Split(metadata, "\n");
|
||||
for (const std::string& line : lines) {
|
||||
std::string str = android::base::Trim(line);
|
||||
if (android::base::StartsWith(str, "pre-build-incremental")) {
|
||||
std::string source_build = parse_build_number(str);
|
||||
if (!source_build.empty()) {
|
||||
log_buffer->push_back("source_build: " + source_build);
|
||||
}
|
||||
} else if (android::base::StartsWith(str, "post-build-incremental")) {
|
||||
std::string target_build = parse_build_number(str);
|
||||
if (!target_build.empty()) {
|
||||
log_buffer->push_back("target_build: " + target_build);
|
||||
}
|
||||
}
|
||||
// Gets the value for the given key in |metadata|. Returns an emtpy string if the key isn't
|
||||
// present.
|
||||
static std::string get_value(const std::map<std::string, std::string>& metadata,
|
||||
const std::string& key) {
|
||||
const auto& it = metadata.find(key);
|
||||
return (it == metadata.end()) ? "" : it->second;
|
||||
}
|
||||
|
||||
static std::string OtaTypeToString(OtaType type) {
|
||||
switch (type) {
|
||||
case OtaType::AB:
|
||||
return "AB";
|
||||
case OtaType::BLOCK:
|
||||
return "BLOCK";
|
||||
case OtaType::BRICK:
|
||||
return "BRICK";
|
||||
}
|
||||
}
|
||||
|
||||
// Parses the metadata of the OTA package in |zip| and checks whether we are allowed to accept this
|
||||
// A/B package. Downgrading is not allowed unless explicitly enabled in the package and only for
|
||||
// Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
|
||||
static void ReadSourceTargetBuild(const std::map<std::string, std::string>& metadata,
|
||||
std::vector<std::string>* log_buffer) {
|
||||
// Examples of the pre-build and post-build strings in metadata:
|
||||
// pre-build-incremental=2943039
|
||||
// post-build-incremental=2951741
|
||||
auto source_build = get_value(metadata, "pre-build-incremental");
|
||||
if (!source_build.empty()) {
|
||||
log_buffer->push_back("source_build: " + source_build);
|
||||
}
|
||||
|
||||
auto target_build = get_value(metadata, "post-build-incremental");
|
||||
if (!target_build.empty()) {
|
||||
log_buffer->push_back("target_build: " + target_build);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks the build version, fingerprint and timestamp in the metadata of the A/B package.
|
||||
// Downgrading is not allowed unless explicitly enabled in the package and only for
|
||||
// incremental packages.
|
||||
static int check_newer_ab_build(ZipArchiveHandle zip) {
|
||||
std::string metadata_str;
|
||||
if (!read_metadata_from_package(zip, &metadata_str)) {
|
||||
return INSTALL_CORRUPT;
|
||||
}
|
||||
std::map<std::string, std::string> metadata;
|
||||
for (const std::string& line : android::base::Split(metadata_str, "\n")) {
|
||||
size_t eq = line.find('=');
|
||||
if (eq != std::string::npos) {
|
||||
metadata[line.substr(0, eq)] = line.substr(eq + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::string value = android::base::GetProperty("ro.product.device", "");
|
||||
const std::string& pkg_device = metadata["pre-device"];
|
||||
if (pkg_device != value || pkg_device.empty()) {
|
||||
LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << value;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
// We allow the package to not have any serialno; and we also allow it to carry multiple serial
|
||||
// numbers split by "|"; e.g. serialno=serialno1|serialno2|serialno3 ... We will fail the
|
||||
// verification if the device's serialno doesn't match any of these carried numbers.
|
||||
value = android::base::GetProperty("ro.serialno", "");
|
||||
const std::string& pkg_serial_no = metadata["serialno"];
|
||||
if (!pkg_serial_no.empty()) {
|
||||
bool match = false;
|
||||
for (const std::string& number : android::base::Split(pkg_serial_no, "|")) {
|
||||
if (value == android::base::Trim(number)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
LOG(ERROR) << "Package is for serial " << pkg_serial_no;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata["ota-type"] != "AB") {
|
||||
LOG(ERROR) << "Package is not A/B";
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata) {
|
||||
// Incremental updates should match the current build.
|
||||
value = android::base::GetProperty("ro.build.version.incremental", "");
|
||||
const std::string& pkg_pre_build = metadata["pre-build-incremental"];
|
||||
if (!pkg_pre_build.empty() && pkg_pre_build != value) {
|
||||
LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected " << value;
|
||||
auto device_pre_build = android::base::GetProperty("ro.build.version.incremental", "");
|
||||
auto pkg_pre_build = get_value(metadata, "pre-build-incremental");
|
||||
if (!pkg_pre_build.empty() && pkg_pre_build != device_pre_build) {
|
||||
LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected "
|
||||
<< device_pre_build;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
value = android::base::GetProperty("ro.build.fingerprint", "");
|
||||
const std::string& pkg_pre_build_fingerprint = metadata["pre-build"];
|
||||
if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != value) {
|
||||
auto device_fingerprint = android::base::GetProperty("ro.build.fingerprint", "");
|
||||
auto pkg_pre_build_fingerprint = get_value(metadata, "pre-build");
|
||||
if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != device_fingerprint) {
|
||||
LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint << " but expected "
|
||||
<< value;
|
||||
<< device_fingerprint;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -194,10 +158,11 @@ static int check_newer_ab_build(ZipArchiveHandle zip) {
|
|||
int64_t pkg_post_timestamp = 0;
|
||||
// We allow to full update to the same version we are running, in case there
|
||||
// is a problem with the current copy of that version.
|
||||
if (metadata["post-timestamp"].empty() ||
|
||||
!android::base::ParseInt(metadata["post-timestamp"].c_str(), &pkg_post_timestamp) ||
|
||||
auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp");
|
||||
if (pkg_post_timestamp_string.empty() ||
|
||||
!android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) ||
|
||||
pkg_post_timestamp < build_timestamp) {
|
||||
if (metadata["ota-downgrade"] != "yes") {
|
||||
if (get_value(metadata, "ota-downgrade") != "yes") {
|
||||
LOG(ERROR) << "Update package is older than the current build, expected a build "
|
||||
"newer than timestamp "
|
||||
<< build_timestamp << " but package has timestamp " << pkg_post_timestamp
|
||||
|
@ -213,13 +178,55 @@ static int check_newer_ab_build(ZipArchiveHandle zip) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type) {
|
||||
auto package_ota_type = get_value(metadata, "ota-type");
|
||||
auto expected_ota_type = OtaTypeToString(ota_type);
|
||||
if (ota_type != OtaType::AB && ota_type != OtaType::BRICK) {
|
||||
LOG(INFO) << "Skip package metadata check for ota type " << expected_ota_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (package_ota_type != expected_ota_type) {
|
||||
LOG(ERROR) << "Unexpected ota package type, expects " << expected_ota_type << ", actual "
|
||||
<< package_ota_type;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
auto device = android::base::GetProperty("ro.product.device", "");
|
||||
auto pkg_device = get_value(metadata, "pre-device");
|
||||
if (pkg_device != device || pkg_device.empty()) {
|
||||
LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << device;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
// We allow the package to not have any serialno; and we also allow it to carry multiple serial
|
||||
// numbers split by "|"; e.g. serialno=serialno1|serialno2|serialno3 ... We will fail the
|
||||
// verification if the device's serialno doesn't match any of these carried numbers.
|
||||
auto pkg_serial_no = get_value(metadata, "serialno");
|
||||
if (!pkg_serial_no.empty()) {
|
||||
auto device_serial_no = android::base::GetProperty("ro.serialno", "");
|
||||
bool serial_number_match = false;
|
||||
for (const auto& number : android::base::Split(pkg_serial_no, "|")) {
|
||||
if (device_serial_no == android::base::Trim(number)) {
|
||||
serial_number_match = true;
|
||||
}
|
||||
}
|
||||
if (!serial_number_match) {
|
||||
LOG(ERROR) << "Package is for serial " << pkg_serial_no;
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ota_type == OtaType::AB) {
|
||||
return CheckAbSpecificMetadata(metadata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd,
|
||||
std::vector<std::string>* cmd) {
|
||||
CHECK(cmd != nullptr);
|
||||
int ret = check_newer_ab_build(zip);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset
|
||||
// in the zip file.
|
||||
|
@ -311,20 +318,33 @@ static void log_max_temperature(int* max_temperature, const std::atomic<bool>& l
|
|||
static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
|
||||
std::vector<std::string>* log_buffer, int retry_count,
|
||||
int* max_temperature) {
|
||||
read_source_target_build(zip, log_buffer);
|
||||
std::map<std::string, std::string> metadata;
|
||||
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);
|
||||
// Verifies against the metadata in the package first.
|
||||
if (int check_status = is_ab ? CheckPackageMetadata(metadata, OtaType::AB) : 0;
|
||||
check_status != 0) {
|
||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
|
||||
return check_status;
|
||||
}
|
||||
|
||||
ReadSourceTargetBuild(metadata, log_buffer);
|
||||
|
||||
int pipefd[2];
|
||||
pipe(pipefd);
|
||||
|
||||
bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false);
|
||||
std::vector<std::string> args;
|
||||
int ret = is_ab ? SetUpAbUpdateCommands(package, zip, pipefd[1], &args)
|
||||
if (int update_status =
|
||||
is_ab ? SetUpAbUpdateCommands(package, zip, pipefd[1], &args)
|
||||
: SetUpNonAbUpdateCommands(package, zip, retry_count, pipefd[1], &args);
|
||||
if (ret) {
|
||||
update_status != 0) {
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
|
||||
return ret;
|
||||
return update_status;
|
||||
}
|
||||
|
||||
// When executing the update binary contained in the package, the
|
||||
|
|
18
install.h
18
install.h
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
@ -33,6 +34,12 @@ enum InstallResult {
|
|||
INSTALL_KEY_INTERRUPTED
|
||||
};
|
||||
|
||||
enum class OtaType {
|
||||
AB,
|
||||
BLOCK,
|
||||
BRICK,
|
||||
};
|
||||
|
||||
// Installs the given update package. If INSTALL_SUCCESS is returned and *wipe_cache is true on
|
||||
// exit, caller should wipe the cache partition.
|
||||
int install_package(const std::string& package, bool* wipe_cache, bool needs_mount,
|
||||
|
@ -42,12 +49,17 @@ int install_package(const std::string& package, bool* wipe_cache, bool needs_mou
|
|||
// otherwise return false.
|
||||
bool verify_package(const unsigned char* package_data, size_t package_size);
|
||||
|
||||
// Read meta data file of the package, write its content in the string pointed by meta_data.
|
||||
// Return true if succeed, otherwise return false.
|
||||
bool read_metadata_from_package(ZipArchiveHandle zip, std::string* metadata);
|
||||
// Reads meta data file of the package; parses each line in the format "key=value"; and writes the
|
||||
// result to |metadata|. Return true if succeed, otherwise return false.
|
||||
bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::string>* metadata);
|
||||
|
||||
// Verifies the compatibility info in a Treble-compatible package. Returns true directly if the
|
||||
// entry doesn't exist.
|
||||
bool verify_package_compatibility(ZipArchiveHandle package_zip);
|
||||
|
||||
// Checks if the the metadata in the OTA package has expected values. Returns 0 on success.
|
||||
// Mandatory checks: ota-type, pre-device and serial number(if presents)
|
||||
// AB OTA specific checks: pre-build version, fingerprint, timestamp.
|
||||
int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type);
|
||||
|
||||
#endif // RECOVERY_INSTALL_H_
|
||||
|
|
31
recovery.cpp
31
recovery.cpp
|
@ -520,34 +520,17 @@ static bool check_wipe_package(size_t wipe_package_size) {
|
|||
LOG(ERROR) << "Can't open wipe package : " << ErrorCodeString(err);
|
||||
return false;
|
||||
}
|
||||
std::string metadata;
|
||||
if (!read_metadata_from_package(zip, &metadata)) {
|
||||
CloseArchive(zip);
|
||||
|
||||
std::map<std::string, std::string> metadata;
|
||||
if (!ReadMetadataFromPackage(zip, &metadata)) {
|
||||
LOG(ERROR) << "Failed to parse metadata in the zip file";
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = CheckPackageMetadata(metadata, OtaType::BRICK);
|
||||
CloseArchive(zip);
|
||||
|
||||
// Check metadata
|
||||
std::vector<std::string> lines = android::base::Split(metadata, "\n");
|
||||
bool ota_type_matched = false;
|
||||
bool device_type_matched = false;
|
||||
bool has_serial_number = false;
|
||||
bool serial_number_matched = false;
|
||||
for (const auto& line : lines) {
|
||||
if (line == "ota-type=BRICK") {
|
||||
ota_type_matched = true;
|
||||
} else if (android::base::StartsWith(line, "pre-device=")) {
|
||||
std::string device_type = line.substr(strlen("pre-device="));
|
||||
std::string real_device_type = android::base::GetProperty("ro.build.product", "");
|
||||
device_type_matched = (device_type == real_device_type);
|
||||
} else if (android::base::StartsWith(line, "serialno=")) {
|
||||
std::string serial_no = line.substr(strlen("serialno="));
|
||||
std::string real_serial_no = android::base::GetProperty("ro.serialno", "");
|
||||
has_serial_number = true;
|
||||
serial_number_matched = (serial_no == real_serial_no);
|
||||
}
|
||||
}
|
||||
return ota_type_matched && device_type_matched && (!has_serial_number || serial_number_matched);
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
// Wipes the current A/B device, with a secure wipe of all the partitions in RECOVERY_WIPE.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -74,15 +75,15 @@ TEST(InstallTest, verify_package_compatibility_invalid_entry) {
|
|||
|
||||
TEST(InstallTest, read_metadata_from_package_smoke) {
|
||||
TemporaryFile temp_file;
|
||||
const std::string content("abcdefg");
|
||||
const std::string content("abc=defg");
|
||||
BuildZipArchive({ { "META-INF/com/android/metadata", content } }, temp_file.release(),
|
||||
kCompressStored);
|
||||
|
||||
ZipArchiveHandle zip;
|
||||
ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
|
||||
std::string metadata;
|
||||
ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
|
||||
ASSERT_EQ(content, metadata);
|
||||
std::map<std::string, std::string> metadata;
|
||||
ASSERT_TRUE(ReadMetadataFromPackage(zip, &metadata));
|
||||
ASSERT_EQ("defg", metadata["abc"]);
|
||||
CloseArchive(zip);
|
||||
|
||||
TemporaryFile temp_file2;
|
||||
|
@ -91,8 +92,8 @@ TEST(InstallTest, read_metadata_from_package_smoke) {
|
|||
|
||||
ASSERT_EQ(0, OpenArchive(temp_file2.path, &zip));
|
||||
metadata.clear();
|
||||
ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
|
||||
ASSERT_EQ(content, metadata);
|
||||
ASSERT_TRUE(ReadMetadataFromPackage(zip, &metadata));
|
||||
ASSERT_EQ("defg", metadata["abc"]);
|
||||
CloseArchive(zip);
|
||||
}
|
||||
|
||||
|
@ -102,8 +103,8 @@ TEST(InstallTest, read_metadata_from_package_no_entry) {
|
|||
|
||||
ZipArchiveHandle zip;
|
||||
ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
|
||||
std::string metadata;
|
||||
ASSERT_FALSE(read_metadata_from_package(zip, &metadata));
|
||||
std::map<std::string, std::string> metadata;
|
||||
ASSERT_FALSE(ReadMetadataFromPackage(zip, &metadata));
|
||||
CloseArchive(zip);
|
||||
}
|
||||
|
||||
|
@ -235,11 +236,11 @@ static void VerifyAbUpdateCommands(const std::string& serialno, bool success = t
|
|||
if (!serialno.empty()) {
|
||||
meta.push_back("serialno=" + serialno);
|
||||
}
|
||||
std::string metadata = android::base::Join(meta, "\n");
|
||||
std::string metadata_string = android::base::Join(meta, "\n");
|
||||
|
||||
BuildZipArchive({ { "payload.bin", "" },
|
||||
{ "payload_properties.txt", properties },
|
||||
{ "META-INF/com/android/metadata", metadata } },
|
||||
{ "META-INF/com/android/metadata", metadata_string } },
|
||||
temp_file.release(), kCompressStored);
|
||||
|
||||
ZipArchiveHandle zip;
|
||||
|
@ -247,10 +248,15 @@ static void VerifyAbUpdateCommands(const std::string& serialno, bool success = t
|
|||
ZipString payload_name("payload.bin");
|
||||
ZipEntry payload_entry;
|
||||
ASSERT_EQ(0, FindEntry(zip, payload_name, &payload_entry));
|
||||
|
||||
std::map<std::string, std::string> metadata;
|
||||
ASSERT_TRUE(ReadMetadataFromPackage(zip, &metadata));
|
||||
if (success) {
|
||||
ASSERT_EQ(0, CheckPackageMetadata(metadata, OtaType::AB));
|
||||
|
||||
int status_fd = 10;
|
||||
std::string package = "/path/to/update.zip";
|
||||
std::vector<std::string> cmd;
|
||||
if (success) {
|
||||
ASSERT_EQ(0, SetUpAbUpdateCommands(package, zip, status_fd, &cmd));
|
||||
ASSERT_EQ(5U, cmd.size());
|
||||
ASSERT_EQ("/system/bin/update_engine_sideload", cmd[0]);
|
||||
|
@ -259,7 +265,7 @@ static void VerifyAbUpdateCommands(const std::string& serialno, bool success = t
|
|||
ASSERT_EQ("--headers=" + properties, cmd[3]);
|
||||
ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]);
|
||||
} else {
|
||||
ASSERT_EQ(INSTALL_ERROR, SetUpAbUpdateCommands(package, zip, status_fd, &cmd));
|
||||
ASSERT_EQ(INSTALL_ERROR, CheckPackageMetadata(metadata, OtaType::AB));
|
||||
}
|
||||
CloseArchive(zip);
|
||||
}
|
||||
|
@ -282,7 +288,11 @@ TEST(InstallTest, SetUpAbUpdateCommands_MissingPayloadPropertiesTxt) {
|
|||
},
|
||||
"\n");
|
||||
|
||||
BuildZipArchive({ { "payload.bin", "" }, { "META-INF/com/android/metadata", metadata } },
|
||||
BuildZipArchive(
|
||||
{
|
||||
{ "payload.bin", "" },
|
||||
{ "META-INF/com/android/metadata", metadata },
|
||||
},
|
||||
temp_file.release(), kCompressStored);
|
||||
|
||||
ZipArchiveHandle zip;
|
||||
|
@ -322,3 +332,241 @@ TEST(InstallTest, SetUpAbUpdateCommands_MultipleSerialnos) {
|
|||
// String with the matching serialno should pass the verification.
|
||||
VerifyAbUpdateCommands(long_serialno);
|
||||
}
|
||||
|
||||
static void test_check_package_metadata(const std::string& metadata_string, OtaType ota_type,
|
||||
int exptected_result) {
|
||||
TemporaryFile temp_file;
|
||||
BuildZipArchive(
|
||||
{
|
||||
{ "META-INF/com/android/metadata", metadata_string },
|
||||
},
|
||||
temp_file.release(), kCompressStored);
|
||||
|
||||
ZipArchiveHandle zip;
|
||||
ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
|
||||
|
||||
std::map<std::string, std::string> metadata;
|
||||
ASSERT_TRUE(ReadMetadataFromPackage(zip, &metadata));
|
||||
ASSERT_EQ(exptected_result, CheckPackageMetadata(metadata, ota_type));
|
||||
CloseArchive(zip);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_ota_type) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
// ota-type must be present
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"pre-device=" + device,
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
|
||||
// Checks if ota-type matches
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, 0);
|
||||
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, INSTALL_ERROR);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_device_type) {
|
||||
// device type can not be empty
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, INSTALL_ERROR);
|
||||
|
||||
// device type mismatches
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=dummy_device_type",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, INSTALL_ERROR);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_serial_number_smoke) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
// Serial number doesn't need to exist
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=" + device,
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, 0);
|
||||
|
||||
// Serial number mismatches
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=" + device,
|
||||
"serialno=dummy_serial",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, INSTALL_ERROR);
|
||||
|
||||
std::string serialno = android::base::GetProperty("ro.serialno", "");
|
||||
ASSERT_NE("", serialno);
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=" + device,
|
||||
"serialno=" + serialno,
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, 0);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_multiple_serial_number) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
std::string serialno = android::base::GetProperty("ro.serialno", "");
|
||||
ASSERT_NE("", serialno);
|
||||
|
||||
std::vector<std::string> serial_numbers;
|
||||
// Creates a dummy serial number string.
|
||||
for (size_t c = 'a'; c <= 'z'; c++) {
|
||||
serial_numbers.emplace_back(c, serialno.size());
|
||||
}
|
||||
|
||||
// No matched serialno found.
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=" + device,
|
||||
"serialno=" + android::base::Join(serial_numbers, '|'),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, INSTALL_ERROR);
|
||||
|
||||
serial_numbers.emplace_back(serialno);
|
||||
std::shuffle(serial_numbers.begin(), serial_numbers.end(), std::default_random_engine());
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=BRICK",
|
||||
"pre-device=" + device,
|
||||
"serialno=" + android::base::Join(serial_numbers, '|'),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::BRICK, 0);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_ab_build_version) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
std::string build_version = android::base::GetProperty("ro.build.version.incremental", "");
|
||||
ASSERT_NE("", build_version);
|
||||
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"pre-build-incremental=" + build_version,
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, 0);
|
||||
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"pre-build-incremental=dummy_build",
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_ab_fingerprint) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
std::string finger_print = android::base::GetProperty("ro.build.fingerprint", "");
|
||||
ASSERT_NE("", finger_print);
|
||||
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"pre-build=" + finger_print,
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, 0);
|
||||
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"pre-build=dummy_build_fingerprint",
|
||||
"post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
}
|
||||
|
||||
TEST(InstallTest, CheckPackageMetadata_ab_post_timestamp) {
|
||||
std::string device = android::base::GetProperty("ro.product.device", "");
|
||||
ASSERT_NE("", device);
|
||||
|
||||
// post timestamp is required for upgrade.
|
||||
std::string metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
|
||||
// post timestamp should be larger than the timestamp on device.
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"post-timestamp=0",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
|
||||
// fingerprint is required for downgrade
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"post-timestamp=0",
|
||||
"ota-downgrade=yes",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, INSTALL_ERROR);
|
||||
|
||||
std::string finger_print = android::base::GetProperty("ro.build.fingerprint", "");
|
||||
ASSERT_NE("", finger_print);
|
||||
|
||||
metadata = android::base::Join(
|
||||
std::vector<std::string>{
|
||||
"ota-type=AB",
|
||||
"pre-device=" + device,
|
||||
"post-timestamp=0",
|
||||
"pre-build=" + finger_print,
|
||||
"ota-downgrade=yes",
|
||||
},
|
||||
"\n");
|
||||
test_check_package_metadata(metadata, OtaType::AB, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue