Restore applypatch/updater/edify for non-A/B OTA support
Google deleted this source from bootable/recovery outright (commit c7ebad5f, "rm -rf non-AB code", 2024-04-05) — confirmed present at android-14, absent at android-16.0.0_r4. The runtime side (install.cpp's SetUpNonAbUpdateCommands) and build-side packaging (ota_from_target_files.py's GenerateNonAbOtaPackage) both survived; only the source that builds the update-binary executable itself was removed. Sourced from TeamWin's android_bootable_recovery (android-14.1), the only living copy found, with install/ZipUtil.cpp, get_args.cpp, and set_metadata.cpp intentionally left out (only wired into TeamWin's modified install.cpp, which PawletOS isn't adopting — twrpinstall carries its own independent copies). Kept as its own repo, not folded into a recovery fork, so it's buildable independent of whichever recovery UI ends up in use.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "updater/build_info.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include "updater/target_files.h"
|
||||
|
||||
bool BuildInfo::ParseTargetFile(const std::string_view target_file_path, bool extracted_input) {
|
||||
TargetFile target_file(std::string(target_file_path), extracted_input);
|
||||
if (!target_file.Open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!target_file.GetBuildProps(&build_props_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<FstabInfo> fstab_info_list;
|
||||
if (!target_file.ParseFstabInfo(&fstab_info_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& fstab_info : fstab_info_list) {
|
||||
for (const auto& directory : { "IMAGES", "RADIO" }) {
|
||||
std::string entry_name = directory + fstab_info.mount_point + ".img";
|
||||
if (!target_file.EntryExists(entry_name)) {
|
||||
LOG(WARNING) << "Failed to find the image entry in the target file: " << entry_name;
|
||||
continue;
|
||||
}
|
||||
|
||||
temp_files_.emplace_back(work_dir_);
|
||||
auto& image_file = temp_files_.back();
|
||||
if (!target_file.ExtractImage(entry_name, fstab_info, work_dir_, &image_file)) {
|
||||
LOG(ERROR) << "Failed to set up source image files.";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string mapped_path = image_file.path;
|
||||
// Rename the images to more readable ones if we want to keep the image.
|
||||
if (keep_images_) {
|
||||
mapped_path = work_dir_ + fstab_info.mount_point + ".img";
|
||||
image_file.release();
|
||||
if (rename(image_file.path, mapped_path.c_str()) != 0) {
|
||||
PLOG(ERROR) << "Failed to rename " << image_file.path << " to " << mapped_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Mounted " << fstab_info.mount_point << "\nMapping: " << fstab_info.blockdev_name
|
||||
<< " to " << mapped_path;
|
||||
|
||||
blockdev_map_.emplace(
|
||||
fstab_info.blockdev_name,
|
||||
FakeBlockDevice(fstab_info.blockdev_name, fstab_info.mount_point, mapped_path));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string BuildInfo::GetProperty(const std::string_view key,
|
||||
const std::string_view default_value) const {
|
||||
// The logic to parse the ro.product properties should be in line with the generation script.
|
||||
// More details in common.py BuildInfo.GetBuildProp.
|
||||
// TODO(xunchang) handle the oem property and the source order defined in
|
||||
// ro.product.property_source_order
|
||||
const std::set<std::string, std::less<>> ro_product_props = {
|
||||
"ro.product.brand", "ro.product.device", "ro.product.manufacturer", "ro.product.model",
|
||||
"ro.product.name"
|
||||
};
|
||||
const std::vector<std::string> source_order = {
|
||||
"product", "odm", "vendor", "system_ext", "system",
|
||||
};
|
||||
if (ro_product_props.find(key) != ro_product_props.end()) {
|
||||
std::string_view key_suffix(key);
|
||||
CHECK(android::base::ConsumePrefix(&key_suffix, "ro.product"));
|
||||
for (const auto& source : source_order) {
|
||||
std::string resolved_key = "ro.product." + source + std::string(key_suffix);
|
||||
if (auto entry = build_props_.find(resolved_key); entry != build_props_.end()) {
|
||||
return entry->second;
|
||||
}
|
||||
}
|
||||
LOG(WARNING) << "Failed to find property: " << key;
|
||||
return std::string(default_value);
|
||||
} else if (key == "ro.build.fingerprint") {
|
||||
// clang-format off
|
||||
return android::base::StringPrintf("%s/%s/%s:%s/%s/%s:%s/%s",
|
||||
GetProperty("ro.product.brand", "").c_str(),
|
||||
GetProperty("ro.product.name", "").c_str(),
|
||||
GetProperty("ro.product.device", "").c_str(),
|
||||
GetProperty("ro.build.version.release", "").c_str(),
|
||||
GetProperty("ro.build.id", "").c_str(),
|
||||
GetProperty("ro.build.version.incremental", "").c_str(),
|
||||
GetProperty("ro.build.type", "").c_str(),
|
||||
GetProperty("ro.build.tags", "").c_str());
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
auto entry = build_props_.find(key);
|
||||
if (entry == build_props_.end()) {
|
||||
LOG(WARNING) << "Failed to find property: " << key;
|
||||
return std::string(default_value);
|
||||
}
|
||||
|
||||
return entry->second;
|
||||
}
|
||||
|
||||
std::string BuildInfo::FindBlockDeviceName(const std::string_view name) const {
|
||||
auto entry = blockdev_map_.find(name);
|
||||
if (entry == blockdev_map_.end()) {
|
||||
LOG(WARNING) << "Failed to find path to block device " << name;
|
||||
return "";
|
||||
}
|
||||
|
||||
return entry->second.mounted_file_path;
|
||||
}
|
||||
Reference in New Issue
Block a user