韌館-LearnHouse

[Android]如何在APP透過USB OTA zip實作AB update

由於一開始是在trace原生的AOSP在recovery mode下是如何透過USB更新,因此這裡還是會紀錄一下native下是如何進行的,然後再說如何使用UpdateEngine這個Java layer的API來實作。

首先,recovery的主程式位在bootable/recovery,在recovery_main.cpp決定要進入fastboot還是recovery模式

auto ret = fastboot ? StartFastboot(device, args) : start_recovery(device, args);

進到recovery.cpp

Device::BuiltinAction start_recovery(Device* device, const std::vector〈std::string〉& args) {
...略...
status = InstallPackage(memory_package.get(), update_package, should_wipe_cache, retry_count, ui);
...略...
}

install.cpp進行驗證和安裝package

InstallResult InstallPackage(Package* package, const std::string_view package_id,
bool should_wipe_cache, int retry_count, RecoveryUI* ui) {
...略...
result = VerifyAndInstallPackage(package, &updater_wipe_cache, &log_buffer, retry_count,
&max_temperature, ui);
...略...
}
static InstallResult VerifyAndInstallPackage(Package* package, bool* wipe_cache,
std::vector<std::string>* log_buffer, int retry_count,
int* max_temperature, RecoveryUI* ui) {
...略...
auto result = TryUpdateBinary(package, wipe_cache, log_buffer, retry_count, max_temperature, ui);
...略...
}
static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache,
std::vector〈std::string〉* log_buffer, int retry_count,
int* max_temperature, RecoveryUI* ui) {
...略...

//確認device是否支援ab update
bool package_is_ab = get_value(metadata, "ota-type") == OtaTypeToString(OtaType::AB);
bool device_supports_ab = android::base::GetBoolProperty("ro.build.ab_update", false);
bool ab_device_supports_nonab =
android::base::GetBoolProperty("ro.virtual_ab.allow_non_ab", false);
bool device_only_supports_ab = device_supports_ab && !ab_device_supports_nonab;

//查看目前security_patch版本,不允許做downgrade
const auto current_spl = android::base::GetProperty("ro.build.version.security_patch", "");
if (ViolatesSPLDowngrade(zip, current_spl)) {
LOG(ERROR) 〈〈 "Denying OTA because it's SPL downgrade";
return INSTALL_ERROR;
}
...略...

//如果是AB update就走SetUpAbUpdateCommands
if (auto setup_result =
package_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;
}
...略...
}
bool SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd,
std::vector〈std::string〉* cmd) {

//取出payload properties
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;
}
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;
}
std::vector〈uint8_t〉 payload_properties(properties_entry_length);
int32_t err =
ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length);
if (err != 0) {
LOG(ERROR) 〈〈 "Failed to extract " 〈〈 AB_OTA_PAYLOAD_PROPERTIES 〈〈 ": " 〈〈 ErrorCodeString(err);
return false;
}

//取出payload.bin在zip檔裡的offset位址
static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
ZipEntry64 payload_entry;
if (FindEntry(zip, AB_OTA_PAYLOAD, &payload_entry) != 0) {
LOG(ERROR) 〈〈 "Failed to find " 〈〈 AB_OTA_PAYLOAD;
return false;
}
long payload_offset = payload_entry.offset;

//執行update_engine_sideload指令進行AB update
*cmd = {
"/system/bin/update_engine_sideload",
"--payload=file://" + package,
android::base::StringPrintf("--offset=%ld", payload_offset),
"--headers=" + std::string(payload_properties.begin(), payload_properties.end()),
android::base::StringPrintf("--status_fd=%d", status_fd),
};
}

而主要在進行更新的主程式位在system/update_engine

2023年7 月 posted by admin in 程式&軟體 and have No Comments

Place your comment

Please fill your data and comment below.
名稱:
信箱:
網站:
您的評論: