diff options
55 files changed, 632 insertions, 273 deletions
diff --git a/Android.bp b/Android.bp index 52de77038..bd9570500 100644 --- a/Android.bp +++ b/Android.bp @@ -157,6 +157,7 @@ cc_binary { ], shared_libs: [ + "android.hardware.health-V1-ndk", // from librecovery_utils "librecovery_ui", ], diff --git a/Android.mk b/Android.mk index 96af417bf..8506040f7 100644 --- a/Android.mk +++ b/Android.mk @@ -45,8 +45,8 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \ $(TARGET_RECOVERY_UI_LIB) LOCAL_SHARED_LIBRARIES := \ - libbase \ - liblog \ + libbase.recovery \ + liblog.recovery \ librecovery_ui.recovery include $(BUILD_SHARED_LIBRARY) @@ -64,9 +64,15 @@ LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) LOCAL_REQUIRED_MODULES += \ make_f2fs.recovery \ + fsck.f2fs.recovery \ sload_f2fs.recovery endif +LOCAL_REQUIRED_MODULES += \ + mkfs.erofs.recovery \ + dump.erofs.recovery \ + fsck.erofs.recovery + # On A/B devices recovery-persist reads the recovery related file from the persist storage and # copies them into /data/misc/recovery. Then, for both A/B and non-A/B devices, recovery-persist # parses the last_install file and reports the embedded update metrics. Also, the last_install file @@ -2,8 +2,8 @@ # CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE # DEPENDING ON IT IN YOUR PROJECT. *** third_party { - # would be NOTICE save for OFL in: - # fonts/README - # fonts/OFL.txt + license_note: "would be NOTICE save for OFL in:\n" + " fonts/README\n" + " fonts/OFL.txt\n" license_type: BY_EXCEPTION_ONLY } @@ -1,5 +1,4 @@ elsk@google.com -enh@google.com nhdo@google.com xunchang@google.com -zhaojiac@google.com +zhangkelvin@google.com diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 28aa06f45..023d48b93 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -6,5 +6,6 @@ clang_format = true clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp [Hook Scripts] +aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "." checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} --file_whitelist tools/ updater_sample/ diff --git a/bootloader_message/bootloader_message.cpp b/bootloader_message/bootloader_message.cpp index b70d54e5c..1ea56cd4e 100644 --- a/bootloader_message/bootloader_message.cpp +++ b/bootloader_message/bootloader_message.cpp @@ -304,6 +304,16 @@ bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::stri offsetof(misc_system_space_layout, virtual_ab_message), err); } +bool ReadMiscMemtagMessage(misc_memtag_message* message, std::string* err) { + return ReadMiscPartitionSystemSpace(message, sizeof(*message), + offsetof(misc_system_space_layout, memtag_message), err); +} + +bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err) { + return WriteMiscPartitionSystemSpace(&message, sizeof(message), + offsetof(misc_system_space_layout, memtag_message), err); +} + extern "C" bool write_reboot_bootloader(void) { std::string err; return write_reboot_bootloader(&err); diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h index e4cf09b22..d58158dd6 100644 --- a/bootloader_message/include/bootloader_message/bootloader_message.h +++ b/bootloader_message/include/bootloader_message/bootloader_message.h @@ -93,18 +93,35 @@ struct misc_virtual_ab_message { uint8_t reserved[57]; } __attribute__((packed)); +struct misc_memtag_message { + uint8_t version; + uint32_t magic; // magic string for treble compat + uint32_t memtag_mode; + uint8_t reserved[55]; +} __attribute__((packed)); + #define MISC_VIRTUAL_AB_MESSAGE_VERSION 2 #define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0 +#define MISC_MEMTAG_MESSAGE_VERSION 1 +#define MISC_MEMTAG_MAGIC_HEADER 0x5afefe5a +#define MISC_MEMTAG_MODE_MEMTAG 0x1 +#define MISC_MEMTAG_MODE_MEMTAG_ONCE 0x2 +#define MISC_MEMTAG_MODE_MEMTAG_KERNEL 0x4 +#define MISC_MEMTAG_MODE_MEMTAG_KERNEL_ONCE 0x8 + #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) static_assert(sizeof(struct misc_virtual_ab_message) == 64, "struct misc_virtual_ab_message has wrong size"); +static_assert(sizeof(struct misc_memtag_message) == 64, + "struct misc_memtag_message has wrong size"); #endif // This struct is not meant to be used directly, rather, it is to make // computation of offsets easier. New fields must be added to the end. struct misc_system_space_layout { misc_virtual_ab_message virtual_ab_message; + misc_memtag_message memtag_message; } __attribute__((packed)); #ifdef __cplusplus @@ -172,6 +189,9 @@ bool write_wipe_package(const std::string& package_data, std::string* err); bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); +// Read or write the memtag message from system space in /misc. +bool ReadMiscMemtagMessage(misc_memtag_message* message, std::string* err); +bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err); #else #include <stdbool.h> diff --git a/edify/parser.yy b/edify/parser.yy index 37bcdd031..5e1e847a6 100644 --- a/edify/parser.yy +++ b/edify/parser.yy @@ -15,6 +15,7 @@ * limitations under the License. */ +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/etc/init.rc b/etc/init.rc index 5cacb8bdb..e4afecff6 100644 --- a/etc/init.rc +++ b/etc/init.rc @@ -38,12 +38,24 @@ on init write /proc/sys/kernel/panic_on_oops 1 write /proc/sys/vm/max_map_count 1000000 + # Mount binderfs + mkdir /dev/binderfs + mount binder binder /dev/binderfs stats=global + chmod 0755 /dev/binderfs + + symlink /dev/binderfs/binder /dev/binder + chmod 0666 /dev/binderfs/binder + + # Start essential services + start servicemanager + on boot ifup lo hostname localhost domainname localdomain class_start default + class_start hal on firmware_mounts_complete rm /dev/.booting diff --git a/fuse_sideload/fuse_provider.cpp b/fuse_sideload/fuse_provider.cpp index 8fa1b5c2e..2183d0844 100644 --- a/fuse_sideload/fuse_provider.cpp +++ b/fuse_sideload/fuse_provider.cpp @@ -118,11 +118,16 @@ bool FuseBlockDataProvider::ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch } if (uint64_t tailing_bytes = fetch_size % source_block_size_; tailing_bytes != 0) { - // Calculate the offset to last partial block. + // Calculate the offset to last partial block. Two possibilities as below: + // 1: fetch_size < source_block_size_, the read_ranges is a blank range_set. + // Get the last block num through GetBlockNumber() of the offset block. + // 2: fetch_size >= source_block_size_, the last block num is already stored + // in read-ranges by GetSubRanges() above. uint64_t tailing_offset = read_ranges.value() ? static_cast<uint64_t>((read_ranges->cend() - 1)->second) * source_block_size_ - : static_cast<uint64_t>(start_block) * source_block_size_; + : static_cast<uint64_t>(ranges_.GetBlockNumber(offset / source_block_size_)) * + source_block_size_; if (!android::base::ReadFullyAtOffset(fd_, next_out, tailing_bytes, tailing_offset)) { PLOG(ERROR) << "Failed to read tailing " << tailing_bytes << " bytes at offset " << tailing_offset; diff --git a/fuse_sideload/fuse_sideload.cpp b/fuse_sideload/fuse_sideload.cpp index 3d9480309..07cbe96f3 100644 --- a/fuse_sideload/fuse_sideload.cpp +++ b/fuse_sideload/fuse_sideload.cpp @@ -225,7 +225,7 @@ static int handle_release(void* /* data */, fuse_data* /* fd */, const fuse_in_h // Fetch a block from the host into fd->curr_block and fd->block_data. // Returns 0 on successful fetch, negative otherwise. -static int fetch_block(fuse_data* fd, uint32_t block) { +static int fetch_block(fuse_data* fd, uint64_t block) { if (block == fd->curr_block) { return 0; } diff --git a/install/Android.bp b/install/Android.bp index e239ddc4e..c59171451 100644 --- a/install/Android.bp +++ b/install/Android.bp @@ -105,12 +105,9 @@ cc_library_static { srcs: [ "adb_install.cpp", - "asn1_decoder.cpp", "fuse_install.cpp", "install.cpp", - "package.cpp", "snapshot_utils.cpp", - "verifier.cpp", "wipe_data.cpp", "wipe_device.cpp", "spl_check.cpp", diff --git a/install/adb_install.cpp b/install/adb_install.cpp index ee79a32c0..b12e52944 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, @@ -368,7 +369,7 @@ InstallResult ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinActi "to the device with \"adb sideload <filename>\"...\n"); } else { command_map.emplace(MinadbdCommand::kWipeData, [&device]() { - bool result = WipeData(device, false); + bool result = WipeData(device); return std::make_pair(result, true); }); command_map.emplace(MinadbdCommand::kNoOp, []() { return std::make_pair(true, true); }); 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 bef23e9ca..0f5102f82 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -24,7 +24,8 @@ #include <ziparchive/zip_archive.h> -#include "package.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/include/install/wipe_data.h b/install/include/install/wipe_data.h index b34891f3d..42cad871e 100644 --- a/install/include/install/wipe_data.h +++ b/install/include/install/wipe_data.h @@ -27,4 +27,4 @@ struct selabel_handle; bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm); // Returns true on success. -bool WipeData(Device* device, bool convert_fbe); +bool WipeData(Device* device); diff --git a/install/include/install/wipe_device.h b/install/include/install/wipe_device.h index c60b99997..903ddfdcd 100644 --- a/install/include/install/wipe_device.h +++ b/install/include/install/wipe_device.h @@ -19,7 +19,7 @@ #include <string> #include <vector> -#include "install/package.h" +#include "otautil/package.h" #include "recovery_ui/device.h" // Wipes the current A/B device, with a secure wipe of all the partitions in RECOVERY_WIPE. diff --git a/install/install.cpp b/install/install.cpp index 6e74f80ab..83f3cad6b 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -46,13 +46,13 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> -#include "install/package.h" #include "install/spl_check.h" -#include "install/verifier.h" #include "install/wipe_data.h" #include "otautil/error_code.h" +#include "otautil/package.h" #include "otautil/paths.h" #include "otautil/sysutil.h" +#include "otautil/verifier.h" #include "private/setup_commands.h" #include "recovery_ui/ui.h" #include "recovery_utils/roots.h" @@ -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); + } + 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/install/wipe_data.cpp b/install/wipe_data.cpp index 4eecf72c6..024c1e1d5 100644 --- a/install/wipe_data.cpp +++ b/install/wipe_data.cpp @@ -16,9 +16,7 @@ #include "install/wipe_data.h" -#include <stdio.h> #include <string.h> -#include <sys/stat.h> #include <functional> #include <vector> @@ -37,9 +35,8 @@ constexpr const char* CACHE_ROOT = "/cache"; constexpr const char* DATA_ROOT = "/data"; constexpr const char* METADATA_ROOT = "/metadata"; -static bool EraseVolume(const char* volume, RecoveryUI* ui, bool convert_fbe) { +static bool EraseVolume(const char* volume, RecoveryUI* ui) { bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); - bool is_data = (strcmp(volume, DATA_ROOT) == 0); std::vector<saved_log_file> log_files; if (is_cache) { @@ -52,28 +49,7 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui, bool convert_fbe) { ensure_path_unmounted(volume); - int result; - if (is_data && convert_fbe) { - constexpr const char* CONVERT_FBE_DIR = "/tmp/convert_fbe"; - constexpr const char* CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe"; - // Create convert_fbe breadcrumb file to signal init to convert to file based encryption, not - // full disk encryption. - if (mkdir(CONVERT_FBE_DIR, 0700) != 0) { - PLOG(ERROR) << "Failed to mkdir " << CONVERT_FBE_DIR; - return false; - } - FILE* f = fopen(CONVERT_FBE_FILE, "wbe"); - if (!f) { - PLOG(ERROR) << "Failed to convert to file encryption"; - return false; - } - fclose(f); - result = format_volume(volume, CONVERT_FBE_DIR); - remove(CONVERT_FBE_FILE); - rmdir(CONVERT_FBE_DIR); - } else { - result = format_volume(volume); - } + int result = format_volume(volume); if (is_cache) { RestoreLogFilesAfterFormat(log_files); @@ -97,12 +73,12 @@ bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) { ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); - bool success = EraseVolume("/cache", ui, false); + bool success = EraseVolume("/cache", ui); ui->Print("Cache wipe %s.\n", success ? "complete" : "failed"); return success; } -bool WipeData(Device* device, bool convert_fbe) { +bool WipeData(Device* device) { RecoveryUI* ui = device->GetUI(); ui->Print("\n-- Wiping data...\n"); ui->SetBackground(RecoveryUI::ERASING); @@ -115,13 +91,13 @@ bool WipeData(Device* device, bool convert_fbe) { bool success = device->PreWipeData(); if (success) { - success &= EraseVolume(DATA_ROOT, ui, convert_fbe); + success &= EraseVolume(DATA_ROOT, ui); bool has_cache = volume_for_mount_point("/cache") != nullptr; if (has_cache) { - success &= EraseVolume(CACHE_ROOT, ui, false); + success &= EraseVolume(CACHE_ROOT, ui); } if (volume_for_mount_point(METADATA_ROOT) != nullptr) { - success &= EraseVolume(METADATA_ROOT, ui, false); + success &= EraseVolume(METADATA_ROOT, ui); } } if (success) { diff --git a/install/wipe_device.cpp b/install/wipe_device.cpp index 915c87b45..0a525fa9b 100644 --- a/install/wipe_device.cpp +++ b/install/wipe_device.cpp @@ -35,7 +35,7 @@ #include "bootloader_message/bootloader_message.h" #include "install/install.h" -#include "install/package.h" +#include "otautil/package.h" #include "recovery_ui/device.h" #include "recovery_ui/ui.h" diff --git a/minadbd/Android.bp b/minadbd/Android.bp index 2bcfece40..9d3f7334a 100644 --- a/minadbd/Android.bp +++ b/minadbd/Android.bp @@ -97,6 +97,7 @@ cc_binary { ], shared_libs: [ + "android.hardware.health-V1-ndk", // from librecovery_utils "libbase", "libcrypto", ], @@ -128,6 +129,7 @@ cc_test { ], static_libs: [ + "android.hardware.health-V1-ndk", // from librecovery_utils "libminadbd_services", "libfusesideload", "librecovery_utils", diff --git a/minadbd/minadbd.cpp b/minadbd/minadbd.cpp index 7b82faa05..1df342c87 100644 --- a/minadbd/minadbd.cpp +++ b/minadbd/minadbd.cpp @@ -64,6 +64,7 @@ int main(int argc, char** argv) { // We can't require authentication for sideloading. http://b/22025550. auth_required = false; + socket_access_allowed = false; init_transport_registration(); usb_init(); diff --git a/minui/Android.bp b/minui/Android.bp index f68f6c81d..02fb3638f 100644 --- a/minui/Android.bp +++ b/minui/Android.bp @@ -24,6 +24,7 @@ package { cc_library { name: "libminui", recovery_available: true, + vendor_available: true, defaults: [ "recovery_defaults", @@ -51,4 +52,15 @@ cc_library { "libpng", "libz", ], + + target: { + vendor: { + exclude_static_libs: [ + "libsync", + ], + shared_libs: [ + "libsync", + ], + }, + }, } diff --git a/minui/events.cpp b/minui/events.cpp index 863ac7474..b307a4977 100644 --- a/minui/events.cpp +++ b/minui/events.cpp @@ -267,6 +267,35 @@ int ev_get_input(int fd, uint32_t epevents, input_event* ev) { return -1; } +int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb) { + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT + unsigned long sw_bits[BITS_TO_LONGS(SW_MAX)]; // NOLINT + + for (size_t i = 0; i < g_ev_dev_count; ++i) { + memset(ev_bits, 0, sizeof(ev_bits)); + memset(sw_bits, 0, sizeof(sw_bits)); + + if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { + continue; + } + if (!test_bit(EV_SW, ev_bits)) { + continue; + } + if (ioctl(ev_fdinfo[i].fd, EVIOCGSW(sizeof(sw_bits)), sw_bits) == -1) { + continue; + } + + for (int code = 0; code <= SW_MAX; code++) { + if (test_bit(code, sw_bits)) { + set_sw_cb(code, 1); + } + } + } + + return 0; +} + int ev_sync_key_state(const ev_set_key_callback& set_key_cb) { // Use unsigned long to match ioctl's parameter type. unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT diff --git a/minui/graphics.cpp b/minui/graphics.cpp index dce1e619a..b24c2b114 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -36,12 +36,14 @@ static int overscan_offset_x = 0; static int overscan_offset_y = 0; static uint32_t gr_current = ~0; -static constexpr uint32_t alpha_mask = 0xff000000; // gr_draw is owned by backends. static GRSurface* gr_draw = nullptr; static GRRotation rotation = GRRotation::NONE; static PixelFormat pixel_format = PixelFormat::UNKNOWN; +// The graphics backend list that provides fallback options for the default backend selection. +// For example, it will fist try DRM, then try FBDEV if DRM is unavailable. +constexpr auto default_backends = { GraphicsBackend::DRM, GraphicsBackend::FBDEV }; static bool outside(int x, int y) { auto swapped = (rotation == GRRotation::LEFT || rotation == GRRotation::RIGHT); @@ -76,7 +78,7 @@ int gr_font_size(const GRFont* font, int* x, int* y) { } // Blends gr_current onto pix value, assumes alpha as most significant byte. -static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) { +static inline uint32_t pixel_blend_argb(uint8_t alpha, uint32_t pix) { if (alpha == 255) return gr_current; if (alpha == 0) return pix; uint32_t pix_r = pix & 0xff; @@ -93,6 +95,48 @@ static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) { return (out_r & 0xff) | (out_g & 0xff00) | (out_b & 0xff0000) | (gr_current & 0xff000000); } +static inline uint32_t pixel_blend_rgba(uint8_t alpha, uint32_t pix) { + if (alpha == 255) return gr_current; + if (alpha == 0) return pix; + uint32_t pix_r = pix & 0xff00; + uint32_t pix_g = pix & 0xff0000; + uint32_t pix_b = pix & 0xff000000; + uint32_t cur_r = gr_current & 0xff00; + uint32_t cur_g = gr_current & 0xff0000; + uint32_t cur_b = gr_current & 0xff000000; + + uint32_t out_r = (pix_r * (255 - alpha) + cur_r * alpha) / 255; + uint32_t out_g = (pix_g * (255 - alpha) + cur_g * alpha) / 255; + uint32_t out_b = (pix_b * (255 - alpha) + cur_b * alpha) / 255; + + return (gr_current & 0xff) | (out_r & 0xff00) | (out_g & 0xff0000) | (out_b & 0xff000000); +} + +static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) { + if (pixel_format == PixelFormat::RGBA) { + return pixel_blend_rgba(alpha, pix); + } + return pixel_blend_argb(alpha, pix); +} + +static inline uint32_t get_alphamask() { + if (pixel_format == PixelFormat::RGBA) { + return 0x000000ff; + } + return 0xff000000; +} + +static inline uint8_t get_alpha_shift() { + if (pixel_format == PixelFormat::RGBA) { + return 0; + } + return 24; +} + +static inline uint8_t get_alpha(uint32_t pix) { + return static_cast<uint8_t>((pix & (gr_current & get_alphamask())) >> get_alpha_shift()); +} + // Increments pixel pointer right, with current rotation. static void incr_x(uint32_t** p, int row_pixels) { if (rotation == GRRotation::LEFT) { @@ -140,7 +184,7 @@ static uint32_t* PixelAt(GRSurface* surface, int x, int y, int row_pixels) { static void TextBlend(const uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, int dst_row_pixels, int width, int height) { - uint8_t alpha_current = static_cast<uint8_t>((alpha_mask & gr_current) >> 24); + uint8_t alpha_current = get_alpha(gr_current); for (int j = 0; j < height; ++j) { const uint8_t* sx = src_p; uint32_t* px = dst_p; @@ -155,7 +199,7 @@ static void TextBlend(const uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, } void gr_text(const GRFont* font, int x, int y, const char* s, bool bold) { - if (!font || !font->texture || (gr_current & alpha_mask) == 0) return; + if (!font || !font->texture || (gr_current & get_alphamask()) == 0) return; if (font->texture->pixel_bytes != 1) { printf("gr_text: font has wrong format\n"); @@ -210,6 +254,8 @@ void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a uint32_t r32 = r, g32 = g, b32 = b, a32 = a; if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) { gr_current = (a32 << 24) | (r32 << 16) | (g32 << 8) | b32; + } else if (pixel_format == PixelFormat::RGBA) { + gr_current = (b32 << 24) | (g32 << 16) | (r32 << 8) | a32; } else { gr_current = (a32 << 24) | (b32 << 16) | (g32 << 8) | r32; } @@ -244,7 +290,7 @@ void gr_fill(int x1, int y1, int x2, int y2) { int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes; uint32_t* p = PixelAt(gr_draw, x1, y1, row_pixels); - uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24)); + uint8_t alpha = get_alpha(gr_current); if (alpha > 0) { for (int y = y1; y < y2; ++y) { uint32_t* px = p; @@ -340,7 +386,22 @@ void gr_flip() { gr_draw = gr_backend->Flip(); } +std::unique_ptr<MinuiBackend> create_backend(GraphicsBackend backend) { + switch (backend) { + case GraphicsBackend::DRM: + return std::make_unique<MinuiBackendDrm>(); + case GraphicsBackend::FBDEV: + return std::make_unique<MinuiBackendFbdev>(); + default: + return nullptr; + } +} + int gr_init() { + return gr_init(default_backends); +} + +int gr_init(std::initializer_list<GraphicsBackend> backends) { // pixel_format needs to be set before loading any resources or initializing backends. std::string format = android::base::GetProperty("ro.minui.pixel_format", ""); if (format == "ABGR_8888") { @@ -351,6 +412,8 @@ int gr_init() { pixel_format = PixelFormat::ARGB; } else if (format == "BGRA_8888") { pixel_format = PixelFormat::BGRA; + } else if (format == "RGBA_8888") { + pixel_format = PixelFormat::RGBA; } else { pixel_format = PixelFormat::UNKNOWN; } @@ -361,19 +424,22 @@ int gr_init() { ret); } - auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendDrm>() }; - gr_draw = backend->Init(); - - if (!gr_draw) { - backend = std::make_unique<MinuiBackendFbdev>(); - gr_draw = backend->Init(); + std::unique_ptr<MinuiBackend> minui_backend; + for (GraphicsBackend backend : backends) { + minui_backend = create_backend(backend); + if (!minui_backend) { + printf("gr_init: minui_backend %d is a nullptr\n", backend); + continue; + } + gr_draw = minui_backend->Init(); + if (gr_draw) break; } if (!gr_draw) { return -1; } - gr_backend = backend.release(); + gr_backend = minui_backend.release(); int overscan_percent = android::base::GetIntProperty("ro.minui.overscan_percent", 0); overscan_offset_x = gr_draw->width * overscan_percent / 100; @@ -429,6 +495,10 @@ void gr_fb_blank(bool blank) { gr_backend->Blank(blank); } +void gr_fb_blank(bool blank, int index) { + gr_backend->Blank(blank, static_cast<MinuiBackend::DrmConnector>(index)); +} + void gr_rotate(GRRotation rot) { rotation = rot; } diff --git a/minui/graphics.h b/minui/graphics.h index 3c45a406b..5408c93e9 100644 --- a/minui/graphics.h +++ b/minui/graphics.h @@ -21,6 +21,12 @@ class MinuiBackend { public: + enum DrmConnector { + DRM_MAIN = 0, + DRM_SEC, + DRM_MAX, + }; + // Initializes the backend and returns a GRSurface* to draw into. virtual GRSurface* Init() = 0; @@ -28,9 +34,12 @@ class MinuiBackend { // be displayed, and returns a new drawing surface. virtual GRSurface* Flip() = 0; - // Blank (or unblank) the screen. + // Blank (or unblank) the default screen. virtual void Blank(bool) = 0; + // Blank (or unblank) the specific screen. + virtual void Blank(bool blank, DrmConnector index) = 0; + // Device cleanup when drawing is done. virtual ~MinuiBackend() {}; }; diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index 95759e382..c55702276 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -105,6 +105,8 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he perror("Failed to DRM_IOCTL_MODE_CREATE_DUMB"); return nullptr; } + printf("Allocating buffer with resolution %d x %d pitch: %d bpp: %d, size: %llu\n", width, height, + create_dumb.pitch, create_dumb.bpp, create_dumb.size); // Cannot use std::make_unique to access non-public ctor. auto surface = std::unique_ptr<GRSurfaceDrm>(new GRSurfaceDrm( @@ -128,13 +130,14 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he return nullptr; } - auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE, - MAP_SHARED, drm_fd, map_dumb.offset); + auto mmapped = + mmap(nullptr, create_dumb.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, map_dumb.offset); if (mmapped == MAP_FAILED) { perror("Failed to mmap()"); return nullptr; } surface->mmapped_buffer_ = static_cast<uint8_t*>(mmapped); + printf("Framebuffer of size %llu allocated @ %p\n", create_dumb.size, surface->mmapped_buffer_); return surface; } @@ -150,22 +153,50 @@ void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) { } bool MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, - const std::unique_ptr<GRSurfaceDrm>& surface) { + const std::unique_ptr<GRSurfaceDrm>& surface, + uint32_t* connector_id) { if (drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y - &main_monitor_connector->connector_id, - 1, // connector_count - &main_monitor_crtc->mode) != 0) { - perror("Failed to drmModeSetCrtc"); + connector_id, 1, // connector_count + &crtc->mode) != 0) { + fprintf(stderr, "Failed to drmModeSetCrtc(%d)\n", *connector_id); return false; } + return true; } void MinuiBackendDrm::Blank(bool blank) { + Blank(blank, DRM_MAIN); +} + +void MinuiBackendDrm::Blank(bool blank, DrmConnector index) { + const auto* drmInterface = &drm[DRM_MAIN]; + + switch (index) { + case DRM_MAIN: + drmInterface = &drm[DRM_MAIN]; + break; + case DRM_SEC: + drmInterface = &drm[DRM_SEC]; + break; + default: + fprintf(stderr, "Invalid index: %d\n", index); + return; + } + + if (!drmInterface->monitor_connector) { + fprintf(stderr, "Unsupported. index = %d\n", index); + return; + } + if (blank) { - DrmDisableCrtc(drm_fd, main_monitor_crtc); + DrmDisableCrtc(drm_fd, drmInterface->monitor_crtc); } else { - DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]); + DrmEnableCrtc(drm_fd, drmInterface->monitor_crtc, + drmInterface->GRSurfaceDrms[drmInterface->current_buffer], + &drmInterface->monitor_connector->connector_id); + + active_display = index; } } @@ -207,18 +238,21 @@ static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources, return nullptr; } -static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) { +std::vector<drmModeConnector*> find_used_connector_by_type(int fd, drmModeRes* resources, + unsigned type) { + std::vector<drmModeConnector*> drmConnectors; for (int i = 0; i < resources->count_connectors; i++) { drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]); if (connector) { if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) && (connector->count_modes > 0)) { - return connector; + drmConnectors.push_back(connector); + } else { + drmModeFreeConnector(connector); } - drmModeFreeConnector(connector); } } - return nullptr; + return drmConnectors; } static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) { @@ -236,8 +270,7 @@ static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* reso return nullptr; } -drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources, - uint32_t* mode_index) { +bool MinuiBackendDrm::FindAndSetMonitor(int fd, drmModeRes* resources) { /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */ static constexpr unsigned kConnectorPriority[] = { DRM_MODE_CONNECTOR_LVDS, @@ -245,30 +278,41 @@ drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources DRM_MODE_CONNECTOR_DSI, }; - drmModeConnector* main_monitor_connector = nullptr; - unsigned i = 0; - do { - main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]); - i++; - } while (!main_monitor_connector && i < arraysize(kConnectorPriority)); + std::vector<drmModeConnector*> drmConnectors; + for (int i = 0; i < arraysize(kConnectorPriority) && drmConnectors.size() < DRM_MAX; i++) { + auto connectors = find_used_connector_by_type(fd, resources, kConnectorPriority[i]); + for (auto connector : connectors) { + drmConnectors.push_back(connector); + if (drmConnectors.size() >= DRM_MAX) break; + } + } /* If we didn't find a connector, grab the first one that is connected. */ - if (!main_monitor_connector) { - main_monitor_connector = find_first_connected_connector(fd, resources); + if (drmConnectors.empty()) { + drmModeConnector* connector = find_first_connected_connector(fd, resources); + if (connector) { + drmConnectors.push_back(connector); + } } - /* If we still didn't find a connector, give up and return. */ - if (!main_monitor_connector) return nullptr; - - *mode_index = 0; - for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) { - if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) { - *mode_index = modes; - break; + for (int drm_index = 0; drm_index < drmConnectors.size(); drm_index++) { + drm[drm_index].monitor_connector = drmConnectors[drm_index]; + + drm[drm_index].selected_mode = 0; + for (int modes = 0; modes < drmConnectors[drm_index]->count_modes; modes++) { + printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes, + drmConnectors[drm_index]->modes[modes].hdisplay, + drmConnectors[drm_index]->modes[modes].vdisplay, + drmConnectors[drm_index]->modes[modes].vrefresh); + if (drmConnectors[drm_index]->modes[modes].type & DRM_MODE_TYPE_PREFERRED) { + printf("Choosing display mode #%d\n", modes); + drm[drm_index].selected_mode = modes; + break; + } } } - return main_monitor_connector; + return drmConnectors.size() > 0; } void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) { @@ -319,46 +363,49 @@ GRSurface* MinuiBackendDrm::Init() { return nullptr; } - uint32_t selected_mode; - main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode); - if (!main_monitor_connector) { - fprintf(stderr, "Failed to find main_monitor_connector\n"); - drmModeFreeResources(res); - close(drm_fd); - return nullptr; - } - - main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector); - if (!main_monitor_crtc) { - fprintf(stderr, "Failed to find main_monitor_crtc\n"); + if (!FindAndSetMonitor(drm_fd, res)) { + fprintf(stderr, "Failed to find main monitor_connector\n"); drmModeFreeResources(res); - close(drm_fd); return nullptr; } - DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc); + for (int i = 0; i < DRM_MAX; i++) { + if (drm[i].monitor_connector) { + drm[i].monitor_crtc = find_crtc_for_connector(drm_fd, res, drm[i].monitor_connector); + if (!drm[i].monitor_crtc) { + fprintf(stderr, "Failed to find monitor_crtc, drm index=%d\n", i); + drmModeFreeResources(res); + return nullptr; + } - main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode]; + drm[i].monitor_crtc->mode = drm[i].monitor_connector->modes[drm[i].selected_mode]; - int width = main_monitor_crtc->mode.hdisplay; - int height = main_monitor_crtc->mode.vdisplay; + int width = drm[i].monitor_crtc->mode.hdisplay; + int height = drm[i].monitor_crtc->mode.vdisplay; - drmModeFreeResources(res); + drm[i].GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height); + drm[i].GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height); + if (!drm[i].GRSurfaceDrms[0] || !drm[i].GRSurfaceDrms[1]) { + fprintf(stderr, "Failed to create GRSurfaceDrm, drm index=%d\n", i); + drmModeFreeResources(res); + return nullptr; + } - GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height); - GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height); - if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) { - return nullptr; + drm[i].current_buffer = 0; + } } - current_buffer = 0; + DisableNonMainCrtcs(drm_fd, res, drm[DRM_MAIN].monitor_crtc); + + drmModeFreeResources(res); // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails. - if (!DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1])) { + if (!DrmEnableCrtc(drm_fd, drm[DRM_MAIN].monitor_crtc, drm[DRM_MAIN].GRSurfaceDrms[1], + &drm[DRM_MAIN].monitor_connector->connector_id)) { return nullptr; } - return GRSurfaceDrms[0].get(); + return drm[DRM_MAIN].GRSurfaceDrms[0].get(); } static void page_flip_complete(__unused int fd, @@ -370,10 +417,19 @@ static void page_flip_complete(__unused int fd, } GRSurface* MinuiBackendDrm::Flip() { + GRSurface* surface = NULL; + DrmInterface* current_drm = &drm[active_display]; bool ongoing_flip = true; - if (drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, GRSurfaceDrms[current_buffer]->fb_id, + + if (!current_drm->monitor_connector) { + fprintf(stderr, "Unsupported. active_display = %d\n", active_display); + return nullptr; + } + + if (drmModePageFlip(drm_fd, current_drm->monitor_crtc->crtc_id, + current_drm->GRSurfaceDrms[current_drm->current_buffer]->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip) != 0) { - perror("Failed to drmModePageFlip"); + fprintf(stderr, "Failed to drmModePageFlip, active_display=%d", active_display); return nullptr; } @@ -399,14 +455,19 @@ GRSurface* MinuiBackendDrm::Flip() { } } - current_buffer = 1 - current_buffer; - return GRSurfaceDrms[current_buffer].get(); + current_drm->current_buffer = 1 - current_drm->current_buffer; + surface = current_drm->GRSurfaceDrms[current_drm->current_buffer].get(); + return surface; } MinuiBackendDrm::~MinuiBackendDrm() { - DrmDisableCrtc(drm_fd, main_monitor_crtc); - drmModeFreeCrtc(main_monitor_crtc); - drmModeFreeConnector(main_monitor_connector); + for (int i = 0; i < DRM_MAX; i++) { + if (drm[i].monitor_connector) { + DrmDisableCrtc(drm_fd, drm[i].monitor_crtc); + drmModeFreeCrtc(drm[i].monitor_crtc); + drmModeFreeConnector(drm[i].monitor_connector); + } + } close(drm_fd); drm_fd = -1; } diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h index 57ba39b83..fe3beaff9 100644 --- a/minui/graphics_drm.h +++ b/minui/graphics_drm.h @@ -59,16 +59,23 @@ class MinuiBackendDrm : public MinuiBackend { GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; + void Blank(bool blank, DrmConnector index) override; private: void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc); - bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface); + bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface, + uint32_t* conntcors); void DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc); - drmModeConnector* FindMainMonitor(int fd, drmModeRes* resources, uint32_t* mode_index); + bool FindAndSetMonitor(int fd, drmModeRes* resources); + + struct DrmInterface { + std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2]; + int current_buffer{ 0 }; + drmModeCrtc* monitor_crtc{ nullptr }; + drmModeConnector* monitor_connector{ nullptr }; + uint32_t selected_mode{ 0 }; + } drm[DRM_MAX]; - std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2]; - int current_buffer{ 0 }; - drmModeCrtc* main_monitor_crtc{ nullptr }; - drmModeConnector* main_monitor_connector{ nullptr }; int drm_fd{ -1 }; + DrmConnector active_display = DRM_MAIN; }; diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp index 2584017d6..1cb0c0ab8 100644 --- a/minui/graphics_fbdev.cpp +++ b/minui/graphics_fbdev.cpp @@ -43,6 +43,10 @@ void MinuiBackendFbdev::Blank(bool blank) { if (ret < 0) perror("ioctl(): blank"); } +void MinuiBackendFbdev::Blank(bool blank, DrmConnector index) { + fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index); +} + void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) { if (n > 1 || !double_buffered) return; @@ -131,8 +135,6 @@ GRSurface* MinuiBackendFbdev::Init() { SetDisplayedFramebuffer(0); printf("framebuffer: %d (%zu x %zu)\n", fb_fd.get(), gr_draw->width, gr_draw->height); - - Blank(true); Blank(false); return gr_draw; diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h index 596ba74ea..7e193c4ff 100644 --- a/minui/graphics_fbdev.h +++ b/minui/graphics_fbdev.h @@ -56,6 +56,7 @@ class MinuiBackendFbdev : public MinuiBackend { GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; + void Blank(bool blank, DrmConnector index) override; private: void SetDisplayedFramebuffer(size_t n); diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h index 163e41dc6..f9be82f52 100644 --- a/minui/include/minui/minui.h +++ b/minui/include/minui/minui.h @@ -102,12 +102,22 @@ enum class PixelFormat : int { RGBX = 2, BGRA = 3, ARGB = 4, + RGBA = 5, // LSB Alpha }; -// Initializes the graphics backend and loads font file. Returns 0 on success, or -1 on error. Note -// that the font initialization failure would be non-fatal, as caller may not need to draw any text -// at all. Caller can check the font initialization result via gr_sys_font() as needed. +enum class GraphicsBackend : int { + UNKNOWN = 0, + DRM = 1, + FBDEV = 2, +}; + +// Initializes the default graphics backend and loads font file. Returns 0 on success, or -1 on +// error. Note that the font initialization failure would be non-fatal, as caller may not need to +// draw any text at all. Caller can check the font initialization result via gr_sys_font() as +// needed. int gr_init(); +// Supports backend selection for minui client. +int gr_init(std::initializer_list<GraphicsBackend> backends); // Frees the allocated resources. The function is idempotent, and safe to be called if gr_init() // didn't finish successfully. @@ -118,6 +128,7 @@ int gr_fb_height(); void gr_flip(); void gr_fb_blank(bool blank); +void gr_fb_blank(bool blank, int index); // Clears entire surface to current color. void gr_clear(); @@ -152,6 +163,7 @@ struct input_event; using ev_callback = std::function<int(int fd, uint32_t epevents)>; using ev_set_key_callback = std::function<int(int code, int value)>; +using ev_set_sw_callback = std::function<int(int code, int value)>; int ev_init(ev_callback input_cb, bool allow_touch_inputs = false); void ev_exit(); @@ -159,6 +171,7 @@ int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb); void ev_iterate_available_keys(const std::function<void(int)>& f); void ev_iterate_touch_inputs(const std::function<void(int)>& action); int ev_sync_key_state(const ev_set_key_callback& set_key_cb); +int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb); // 'timeout' has the same semantics as poll(2). // 0 : don't block diff --git a/minui/resources.cpp b/minui/resources.cpp index d7b927700..1521c8f17 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -153,32 +153,57 @@ static void TransformRgbToDraw(const uint8_t* input_row, uint8_t* output_row, in int width) { const uint8_t* ip = input_row; uint8_t* op = output_row; + PixelFormat pixel_format = gr_pixel_format(); switch (channels) { case 1: // expand gray level to RGBX for (int x = 0; x < width; ++x) { - *op++ = *ip; - *op++ = *ip; - *op++ = *ip; - *op++ = 0xff; + if (pixel_format == PixelFormat::RGBA) { + *op++ = 0xff; + *op++ = *ip; + *op++ = *ip; + *op++ = *ip; + } else { + *op++ = *ip; + *op++ = *ip; + *op++ = *ip; + *op++ = 0xff; + } ip++; } break; case 3: - // expand RGBA to RGBX for (int x = 0; x < width; ++x) { - *op++ = *ip++; - *op++ = *ip++; - *op++ = *ip++; - *op++ = 0xff; + // expand RGBA to RGBX + if (pixel_format == PixelFormat::RGBA) { + *op++ = 0xff; + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + } else { + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + *op++ = 0xff; + } } break; case 4: - // copy RGBA to RGBX - memcpy(output_row, input_row, width * 4); + if (pixel_format == PixelFormat::RGBA) { + for (int x = 0; x < width; ++x) { + *op++ = *(ip + 3); + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + ip++; + } + } else { + // copy RGBA to RGBX + memcpy(output_row, input_row, width * 4); + } break; } } @@ -201,6 +226,8 @@ int res_create_display_surface(const char* name, GRSurface** pSurface) { PixelFormat pixel_format = gr_pixel_format(); if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) { png_set_bgr(png_ptr); + } else if (pixel_format == PixelFormat::RGBA) { + png_set_swap_alpha(png_ptr); } for (png_uint_32 y = 0; y < height; ++y) { @@ -273,6 +300,8 @@ int res_create_multi_display_surface(const char* name, int* frames, int* fps, if (gr_pixel_format() == PixelFormat::ARGB || gr_pixel_format() == PixelFormat::BGRA) { png_set_bgr(png_ptr); + } else if (gr_pixel_format() == PixelFormat::RGBA) { + png_set_swap_alpha(png_ptr); } for (png_uint_32 y = 0; y < height; ++y) { @@ -316,11 +345,6 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) { return -8; } - PixelFormat pixel_format = gr_pixel_format(); - if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) { - png_set_bgr(png_ptr); - } - for (png_uint_32 y = 0; y < height; ++y) { uint8_t* p_row = surface->data() + y * surface->row_bytes; png_read_row(png_ptr, p_row, nullptr); diff --git a/otautil/Android.bp b/otautil/Android.bp index 557b8a313..4b043adf1 100644 --- a/otautil/Android.bp +++ b/otautil/Android.bp @@ -34,16 +34,21 @@ cc_library_static { // Minimal set of files to support host build. srcs: [ + "asn1_decoder.cpp", "dirutil.cpp", + "package.cpp", "paths.cpp", "rangeset.cpp", "sysutil.cpp", + "verifier.cpp", ], shared_libs: [ "libbase", + "libcrypto", "libcutils", "libselinux", + "libziparchive", ], export_include_dirs: [ diff --git a/install/asn1_decoder.cpp b/otautil/asn1_decoder.cpp index 2d81a6e13..2d81a6e13 100644 --- a/install/asn1_decoder.cpp +++ b/otautil/asn1_decoder.cpp diff --git a/install/include/install/package.h b/otautil/include/otautil/package.h index 0b4233238..f4f4d348b 100644 --- a/install/include/install/package.h +++ b/otautil/include/otautil/package.h @@ -26,7 +26,7 @@ #include <ziparchive/zip_archive.h> -#include "verifier.h" +#include "otautil/verifier.h" enum class PackageType { kMemory, diff --git a/install/include/install/verifier.h b/otautil/include/otautil/verifier.h index f9e947580..f9e947580 100644 --- a/install/include/install/verifier.h +++ b/otautil/include/otautil/verifier.h diff --git a/install/include/private/asn1_decoder.h b/otautil/include/private/asn1_decoder.h index e5337d9c4..e5337d9c4 100644 --- a/install/include/private/asn1_decoder.h +++ b/otautil/include/private/asn1_decoder.h diff --git a/install/package.cpp b/otautil/package.cpp index 86fc0647d..242204ee6 100644 --- a/install/package.cpp +++ b/otautil/package.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "install/package.h" +#include "otautil/package.h" #include <string.h> #include <unistd.h> diff --git a/install/verifier.cpp b/otautil/verifier.cpp index 3f0260138..8a65566ec 100644 --- a/install/verifier.cpp +++ b/otautil/verifier.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "install/verifier.h" +#include "otautil/verifier.h" #include <errno.h> #include <stdio.h> @@ -257,8 +257,8 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys // Check to make sure at least one of the keys matches the signature. Since any key can match, // we need to try each before determining a verification failure has happened. - size_t i = 0; - for (const auto& key : keys) { + for (size_t i = 0; i < keys.size(); i++) { + const auto& key = keys[i]; const uint8_t* hash; int hash_nid; switch (key.hash_len) { @@ -296,7 +296,6 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys } else { LOG(INFO) << "Unknown key type " << key.key_type; } - i++; } if (need_sha1) { diff --git a/recovery.cpp b/recovery.cpp index 36924fbdf..4d3901959 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -48,12 +48,12 @@ #include "install/adb_install.h" #include "install/fuse_install.h" #include "install/install.h" -#include "install/package.h" #include "install/snapshot_utils.h" #include "install/wipe_data.h" #include "install/wipe_device.h" #include "otautil/boot_state.h" #include "otautil/error_code.h" +#include "otautil/package.h" #include "otautil/paths.h" #include "otautil/sysutil.h" #include "recovery_ui/screen_ui.h" @@ -207,8 +207,7 @@ static InstallResult prompt_and_wipe_data(Device* device) { if (ask_to_wipe_data(device)) { CHECK(device->GetReason().has_value()); - bool convert_fbe = device->GetReason().value() == "convert_fbe"; - if (WipeData(device, convert_fbe)) { + if (WipeData(device)) { return INSTALL_SUCCESS; } else { return INSTALL_ERROR; @@ -437,10 +436,10 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status) save_current_log = true; if (ui->IsTextVisible()) { if (ask_to_wipe_data(device)) { - WipeData(device, false); + WipeData(device); } } else { - WipeData(device, false); + WipeData(device); return Device::NO_ACTION; } break; @@ -752,20 +751,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"); @@ -794,8 +793,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } else if (should_wipe_data) { save_current_log = true; CHECK(device->GetReason().has_value()); - bool convert_fbe = device->GetReason().value() == "convert_fbe"; - if (!WipeData(device, convert_fbe)) { + if (!WipeData(device)) { status = INSTALL_ERROR; } } else if (should_prompt_and_wipe_data) { diff --git a/recovery_main.cpp b/recovery_main.cpp index 80cba61d3..9a358aba7 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -73,12 +73,12 @@ static bool IsDeviceUnlocked() { return "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", ""); } -static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity, - const char* /* tag */, const char* /* file */, unsigned int /* line */, - const char* message) { - static constexpr char log_characters[] = "VDIWEF"; +static void UiLogger(android::base::LogId log_buffer_id, android::base::LogSeverity severity, + const char* tag, const char* file, unsigned int line, const char* message) { + android::base::KernelLogger(log_buffer_id, severity, tag, file, line, message); + static constexpr auto&& log_characters = "VDIWEF"; if (severity >= android::base::ERROR && ui != nullptr) { - ui->Print("E:%s\n", message); + ui->Print("ERROR: %10s: %s\n", tag, message); } else { fprintf(stdout, "%c:%s\n", log_characters[severity], message); } diff --git a/recovery_ui/ethernet_device.cpp b/recovery_ui/ethernet_device.cpp index d79f41dec..0318db853 100644 --- a/recovery_ui/ethernet_device.cpp +++ b/recovery_ui/ethernet_device.cpp @@ -30,10 +30,12 @@ #include "recovery_ui/ethernet_device.h" #include "recovery_ui/ethernet_ui.h" -const std::string EthernetDevice::interface = "eth0"; +// Android TV defaults to eth0 for it's interface +EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) : EthernetDevice(ui, "eth0") {} -EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) - : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) { +// Allow future users to define the interface as they prefer +EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui, std::string interface) + : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)), interface_(interface) { if (ctl_sock_ < 0) { PLOG(ERROR) << "Failed to open socket"; } @@ -63,7 +65,7 @@ int EthernetDevice::SetInterfaceFlags(const unsigned set, const unsigned clr) { } memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ); + strncpy(ifr.ifr_name, interface_.c_str(), IFNAMSIZ); ifr.ifr_name[IFNAMSIZ - 1] = 0; if (ioctl(ctl_sock_, SIOCGIFFLAGS, &ifr) < 0) { @@ -96,7 +98,7 @@ void EthernetDevice::SetTitleIPv6LinkLocalAddress(const bool interface_up) { std::unique_ptr<struct ifaddrs, decltype(&freeifaddrs)> guard{ ifaddr, freeifaddrs }; for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != AF_INET6 || interface != ifa->ifa_name) { + if (ifa->ifa_addr->sa_family != AF_INET6 || interface_ != ifa->ifa_name) { continue; } diff --git a/recovery_ui/include/recovery_ui/ethernet_device.h b/recovery_ui/include/recovery_ui/ethernet_device.h index ea710ab93..3aadea200 100644 --- a/recovery_ui/include/recovery_ui/ethernet_device.h +++ b/recovery_ui/include/recovery_ui/ethernet_device.h @@ -27,6 +27,7 @@ class EthernetRecoveryUI; class EthernetDevice : public Device { public: explicit EthernetDevice(EthernetRecoveryUI* ui); + explicit EthernetDevice(EthernetRecoveryUI* ui, std::string interface); void PreRecovery() override; void PreFastboot() override; @@ -36,7 +37,7 @@ class EthernetDevice : public Device { void SetTitleIPv6LinkLocalAddress(const bool interface_up); android::base::unique_fd ctl_sock_; - static const std::string interface; + std::string interface_; }; #endif // _ETHERNET_RECOVERY_DEVICE_H diff --git a/recovery_utils/Android.bp b/recovery_utils/Android.bp index e0e9ec058..9bd66c5d9 100644 --- a/recovery_utils/Android.bp +++ b/recovery_utils/Android.bp @@ -31,6 +31,7 @@ cc_defaults { shared_libs: [ "android.hardware.health@2.0", "libbase", + "libbinder_ndk", "libext4_utils", "libfs_mgr", "libhidlbase", @@ -42,8 +43,10 @@ cc_defaults { "libotautil", // External dependencies. + "android.hardware.health-translate-ndk", "libfstab", "libhealthhalutils", + "libhealthshim", ], } @@ -70,6 +73,15 @@ cc_library_static { "libvold_headers", ], + shared_libs: [ + // The following cannot be placed in librecovery_utils_defaults, + // because at the time of writing, android.hardware.health-V1-ndk.so + // is not installed to the system image yet. (It is installed + // to the recovery ramdisk.) Hence, minadbd_test must link to it + // statically. + "android.hardware.health-V1-ndk", + ], + export_include_dirs: [ "include", ], diff --git a/recovery_utils/battery_utils.cpp b/recovery_utils/battery_utils.cpp index 323f52537..6b126bdf3 100644 --- a/recovery_utils/battery_utils.cpp +++ b/recovery_utils/battery_utils.cpp @@ -20,59 +20,74 @@ #include <unistd.h> #include <android-base/logging.h> +#include <android/binder_manager.h> +#include <health-shim/shim.h> #include <healthhalutils/HealthHalUtils.h> BatteryInfo GetBatteryInfo() { - using android::hardware::health::V1_0::BatteryStatus; using android::hardware::health::V2_0::get_health_service; - using android::hardware::health::V2_0::IHealth; - using android::hardware::health::V2_0::Result; - using android::hardware::health::V2_0::toString; + using HidlHealth = android::hardware::health::V2_0::IHealth; + using aidl::android::hardware::health::BatteryStatus; + using aidl::android::hardware::health::HealthShim; + using aidl::android::hardware::health::IHealth; + using aidl::android::hardware::health::toString; + using std::string_literals::operator""s; - android::sp<IHealth> health = get_health_service(); + auto service_name = IHealth::descriptor + "/default"s; + std::shared_ptr<IHealth> health; + if (AServiceManager_isDeclared(service_name.c_str())) { + ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str())); + health = IHealth::fromBinder(binder); + } + if (health == nullptr) { + LOG(INFO) << "Unable to get AIDL health service, trying HIDL..."; + android::sp<HidlHealth> hidl_health = get_health_service(); + if (hidl_health != nullptr) { + health = ndk::SharedRefBase::make<HealthShim>(hidl_health); + } + } + if (health == nullptr) { + LOG(WARNING) << "No health implementation is found; assuming defaults"; + } int wait_second = 0; while (true) { auto charge_status = BatteryStatus::UNKNOWN; - - if (health == nullptr) { - LOG(WARNING) << "No health implementation is found; assuming defaults"; - } else { - health - ->getChargeStatus([&charge_status](auto res, auto out_status) { - if (res == Result::SUCCESS) { - charge_status = out_status; - } - }) - .isOk(); // should not have transport error + if (health != nullptr) { + auto res = health->getChargeStatus(&charge_status); + if (!res.isOk()) { + LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription(); + charge_status = BatteryStatus::UNKNOWN; + } } - // Treat unknown status as on charger. See hardware/interfaces/health/1.0/types.hal for the - // meaning of the return values. + // Treat unknown status as on charger. See hardware/interfaces/health/aidl/BatteryStatus.aidl + // for the meaning of the return values. bool charging = (charge_status != BatteryStatus::DISCHARGING && charge_status != BatteryStatus::NOT_CHARGING); - Result res = Result::UNKNOWN; int32_t capacity = INT32_MIN; if (health != nullptr) { - health - ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { - res = out_res; - capacity = out_capacity; - }) - .isOk(); // should not have transport error + auto res = health->getCapacity(&capacity); + if (!res.isOk()) { + LOG(WARNING) << "Unable to call getCapacity: " << res.getDescription(); + capacity = INT32_MIN; + } } LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging - << ", status " << toString(res) << ", capacity " << capacity; + << ", capacity " << capacity; constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10; // At startup, the battery drivers in devices like N5X/N6P take some time to load // the battery profile. Before the load finishes, it reports value 50 as a fake // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected // to finish loading the battery profile earlier than 10 seconds after kernel startup. - if (res == Result::SUCCESS && capacity == 50) { + if (capacity == 50) { if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) { + LOG(INFO) << "Battery capacity == 50, waiting " + << (BATTERY_READ_TIMEOUT_IN_SEC - wait_second) + << " seconds to ensure this is not a fake value..."; sleep(1); wait_second++; continue; @@ -80,10 +95,12 @@ BatteryInfo GetBatteryInfo() { } // If we can't read battery percentage, it may be a device without battery. In this // situation, use 100 as a fake battery percentage. - if (res != Result::SUCCESS) { + if (capacity == INT32_MIN) { + LOG(WARNING) << "Using fake battery capacity 100."; capacity = 100; } + LOG(INFO) << "GetBatteryInfo() reporting charging " << charging << ", capacity " << capacity; return BatteryInfo{ charging, capacity }; } } diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp index 19484478c..5c95cba07 100644 --- a/recovery_utils/roots.cpp +++ b/recovery_utils/roots.cpp @@ -33,7 +33,7 @@ #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> -#include <cryptfs.h> +#include <ext4_utils/ext4_utils.h> #include <ext4_utils/wipe.h> #include <fs_mgr.h> #include <fs_mgr/roots.h> @@ -154,53 +154,56 @@ int format_volume(const std::string& volume, const std::string& directory) { } bool needs_casefold = false; - bool needs_projid = false; if (volume == "/data") { needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false); - needs_projid = android::base::GetBoolProperty("external_storage.projid.enabled", false); - } - - // If there's a key_loc that looks like a path, it should be a block device for storing encryption - // metadata. Wipe it too. - if (!v->key_loc.empty() && v->key_loc[0] == '/') { - LOG(INFO) << "Wiping " << v->key_loc; - int fd = open(v->key_loc.c_str(), O_WRONLY | O_CREAT, 0644); - if (fd == -1) { - PLOG(ERROR) << "format_volume: Failed to open " << v->key_loc; - return -1; - } - wipe_block_device(fd, get_file_size(fd)); - close(fd); } int64_t length = 0; if (v->length > 0) { length = v->length; - } else if (v->length < 0 || v->key_loc == "footer") { + } else if (v->length < 0) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } - length = get_file_size(fd.get(), v->length ? -v->length : CRYPT_FOOTER_OFFSET); + length = get_file_size(fd.get(), -v->length); if (length <= 0) { LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device; return -1; } } + // If the raw disk will be used as a metadata encrypted device mapper target, + // next boot will do encrypt_in_place the raw disk which gives a subtle duration + // to get any failure in the process. In order to avoid it, let's simply wipe + // the raw disk if we don't reserve any space, which behaves exactly same as booting + // after "fastboot -w". + if (!v->metadata_key_dir.empty() && length == 0) { + android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR)); + if (fd == -1) { + PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; + return -1; + } + int64_t device_size = get_file_size(fd.get(), 0); + if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) { + LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size " + << device_size; + return 0; + } + } + if (v->fs_type == "ext4") { static constexpr int kBlockSize = 4096; std::vector<std::string> mke2fs_args = { "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), }; - // Project ID's require wider inodes. The Quotas themselves are enabled by tune2fs on boot. - if (needs_projid) { - mke2fs_args.push_back("-I"); - mke2fs_args.push_back("512"); - } + // Following is added for Project ID's quota as they require wider inodes. + // The Quotas themselves are enabled by tune2fs on boot. + mke2fs_args.push_back("-I"); + mke2fs_args.push_back("512"); if (v->fs_mgr_flags.ext_meta_csum) { mke2fs_args.push_back("-O"); @@ -249,10 +252,10 @@ int format_volume(const std::string& volume, const std::string& directory) { "-g", "android", }; - if (needs_projid) { - make_f2fs_cmd.push_back("-O"); - make_f2fs_cmd.push_back("project_quota,extra_attr"); - } + + make_f2fs_cmd.push_back("-O"); + make_f2fs_cmd.push_back("project_quota,extra_attr"); + if (needs_casefold) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("casefold"); diff --git a/tests/Android.bp b/tests/Android.bp index 5ef4d58c0..9ad3d3b80 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -134,11 +134,22 @@ cc_test { test_suites: ["device-tests"], + tidy_timeout_srcs: [ + "unit/commands_test.cpp", + ], + srcs: [ "unit/*.cpp", ], + shared_libs: [ + "libbinder_ndk", + ], + static_libs: libapplypatch_static_libs + librecovery_static_libs + [ + "android.hardware.health-translate-ndk", + "android.hardware.health-V1-ndk", + "libhealthshim", "librecovery_ui", "libfusesideload", "libminui", @@ -185,6 +196,10 @@ cc_test_host { "libupdater_defaults", ], + tidy_timeout_srcs: [ + "unit/host/imgdiff_test.cpp", + ], + srcs: [ "unit/host/*", ], diff --git a/tests/fuzz/verify_package_fuzzer.cpp b/tests/fuzz/verify_package_fuzzer.cpp index baa44e070..36c853465 100644 --- a/tests/fuzz/verify_package_fuzzer.cpp +++ b/tests/fuzz/verify_package_fuzzer.cpp @@ -17,7 +17,7 @@ #include "fuzzer/FuzzedDataProvider.h" #include "install/install.h" -#include "install/package.h" +#include "otautil/package.h" #include "recovery_ui/stub_ui.h" std::unique_ptr<Package> CreatePackage(std::vector<uint8_t>& content) { diff --git a/tests/unit/host/update_simulator_test.cpp b/tests/unit/host/update_simulator_test.cpp index fb1217877..1603982e4 100644 --- a/tests/unit/host/update_simulator_test.cpp +++ b/tests/unit/host/update_simulator_test.cpp @@ -101,7 +101,7 @@ static void RunSimulation(std::string_view src_tf, std::string_view ota_package, // TODO(xunchang) check the recovery&system has the expected contents. } -class UpdateSimulatorTest : public ::testing::Test { +class DISABLED_UpdateSimulatorTest : public ::testing::Test { protected: void SetUp() override { std::vector<string> props = { @@ -147,7 +147,7 @@ class UpdateSimulatorTest : public ::testing::Test { string sparse_system_string_; }; -TEST_F(UpdateSimulatorTest, TargetFile_ExtractImage) { +TEST_F(DISABLED_UpdateSimulatorTest, TargetFile_ExtractImage) { TemporaryFile zip_file; AddZipEntries(zip_file.release(), { { "META/misc_info.txt", "extfs_sparse_flag=-s" }, { "IMAGES/system.img", sparse_system_string_ } }); @@ -166,7 +166,7 @@ TEST_F(UpdateSimulatorTest, TargetFile_ExtractImage) { ASSERT_EQ(expected_content, content); } -TEST_F(UpdateSimulatorTest, TargetFile_ParseFstabInfo) { +TEST_F(DISABLED_UpdateSimulatorTest, TargetFile_ParseFstabInfo) { TemporaryFile zip_file; AddZipEntries(zip_file.release(), { { "META/misc_info.txt", "" }, @@ -195,7 +195,7 @@ TEST_F(UpdateSimulatorTest, TargetFile_ParseFstabInfo) { EXPECT_EQ(expected, transformed); } -TEST_F(UpdateSimulatorTest, BuildInfo_ParseTargetFile) { +TEST_F(DISABLED_UpdateSimulatorTest, BuildInfo_ParseTargetFile) { std::map<string, string> entries = { { "META/misc_info.txt", "" }, { "SYSTEM/build.prop", build_prop_string_ }, @@ -240,7 +240,7 @@ TEST_F(UpdateSimulatorTest, BuildInfo_ParseTargetFile) { } } -TEST_F(UpdateSimulatorTest, RunUpdateSmoke) { +TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateSmoke) { string recovery_img_string = "recovery.img"; string boot_img_string = "boot.img"; @@ -326,7 +326,7 @@ TEST_F(UpdateSimulatorTest, RunUpdateSmoke) { RunSimulation(src_tf.path, ota_package.path, true); } -TEST_F(UpdateSimulatorTest, RunUpdateUnrecognizedFunction) { +TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateUnrecognizedFunction) { std::map<string, string> src_entries{ { "META/misc_info.txt", "extfs_sparse_flag=-s" }, { "IMAGES/system.img", sparse_system_string_ }, @@ -350,7 +350,7 @@ TEST_F(UpdateSimulatorTest, RunUpdateUnrecognizedFunction) { RunSimulation(src_tf.path, ota_package.path, false); } -TEST_F(UpdateSimulatorTest, RunUpdateApplyPatchFailed) { +TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateApplyPatchFailed) { string recovery_img_string = "recovery.img"; string boot_img_string = "boot.img"; diff --git a/tests/unit/package_test.cpp b/tests/unit/package_test.cpp index 164a93d57..66882bb40 100644 --- a/tests/unit/package_test.cpp +++ b/tests/unit/package_test.cpp @@ -26,7 +26,7 @@ #include <ziparchive/zip_writer.h> #include "common/test_constants.h" -#include "install/package.h" +#include "otautil/package.h" class PackageTest : public ::testing::Test { protected: diff --git a/tests/unit/verifier_test.cpp b/tests/unit/verifier_test.cpp index ded23c52f..08a3ddfc4 100644 --- a/tests/unit/verifier_test.cpp +++ b/tests/unit/verifier_test.cpp @@ -35,8 +35,8 @@ #include <ziparchive/zip_writer.h> #include "common/test_constants.h" -#include "install/package.h" -#include "install/verifier.h" +#include "otautil/package.h" +#include "otautil/verifier.h" #include "otautil/sysutil.h" using namespace std::string_literals; diff --git a/tools/recovery_l10n/res/values-ky/strings.xml b/tools/recovery_l10n/res/values-ky/strings.xml index 67dca2a37..45fcd15e0 100644 --- a/tools/recovery_l10n/res/values-ky/strings.xml +++ b/tools/recovery_l10n/res/values-ky/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recovery_installing" msgid="2013591905463558223">"Система жаңырууда"</string> + <string name="recovery_installing" msgid="2013591905463558223">"Тутум жаңырууда"</string> <string name="recovery_erasing" msgid="7334826894904037088">"Тазаланууда"</string> <string name="recovery_no_command" msgid="4465476568623024327">"Буйрук берилген жок"</string> <string name="recovery_error" msgid="5748178989622716736">"Ката!"</string> diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp index ff2eff903..220b007f5 100644 --- a/update_verifier/Android.bp +++ b/update_verifier/Android.bp @@ -33,6 +33,25 @@ cc_defaults { ], } +python_library_host { + name: "care_map_proto_py", + srcs: [ + "care_map.proto", + ], + proto: {type: "lite", canonical_path_from_root: false}, + version: { + py2: { + enabled: true, + }, + py3: { + enabled: true, + }, + }, + visibility: [ + "//build/make/tools/releasetools:__subpackages__", + ], +} + cc_library_static { name: "libupdate_verifier", diff --git a/update_verifier/care_map_generator.py b/update_verifier/care_map_generator.py index c6f2dad24..b1396a43c 100644 --- a/update_verifier/care_map_generator.py +++ b/update_verifier/care_map_generator.py @@ -111,14 +111,14 @@ def main(argv): logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING, format=logging_format) - with open(args.input_care_map, 'r') as input_care_map: + with open(args.input_care_map, 'rb') as input_care_map: content = input_care_map.read() if args.parse_proto: result = ParseProtoMessage(content, args.fingerprint_enabled).encode() else: care_map_proto = GenerateCareMapProtoFromLegacyFormat( - content.rstrip().splitlines(), args.fingerprint_enabled) + content.decode().rstrip().splitlines(), args.fingerprint_enabled) result = care_map_proto.SerializeToString() with open(args.output_file, 'wb') as output: |