DO NOT MERGE - Skip SQ3A.220605.009
Bug: 236045730
Merged-In: I1a3e3f0be9b79ec4c309be8e257afbacd1336cdc
Change-Id: Ib017b0dfa357aaeabd24d7b0f44059b804de36ae
diff --git a/Android.bp b/Android.bp
index 52de770..bd95705 100644
--- a/Android.bp
+++ b/Android.bp
@@ -157,6 +157,7 @@
],
shared_libs: [
+ "android.hardware.health-V1-ndk", // from librecovery_utils
"librecovery_ui",
],
diff --git a/Android.mk b/Android.mk
index 96af417..8506040 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,8 +45,8 @@
$(TARGET_RECOVERY_UI_LIB)
LOCAL_SHARED_LIBRARIES := \
- libbase \
- liblog \
+ libbase.recovery \
+ liblog.recovery \
librecovery_ui.recovery
include $(BUILD_SHARED_LIBRARY)
@@ -64,9 +64,15 @@
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
diff --git a/METADATA b/METADATA
index a1ce3c6..68bf6f8 100644
--- a/METADATA
+++ b/METADATA
@@ -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
}
diff --git a/OWNERS b/OWNERS
index 79dd9f7..45c72e3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -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 28aa06f..023d48b 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,5 +6,6 @@
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 b70d54e..1ea56cd 100644
--- a/bootloader_message/bootloader_message.cpp
+++ b/bootloader_message/bootloader_message.cpp
@@ -304,6 +304,16 @@
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 e4cf09b..d58158d 100644
--- a/bootloader_message/include/bootloader_message/bootloader_message.h
+++ b/bootloader_message/include/bootloader_message/bootloader_message.h
@@ -93,18 +93,35 @@
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 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 37bcdd0..5e1e847 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 5cacb8b..e4afecf 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -38,12 +38,24 @@
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 8fa1b5c..2183d08 100644
--- a/fuse_sideload/fuse_provider.cpp
+++ b/fuse_sideload/fuse_provider.cpp
@@ -118,11 +118,16 @@
}
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 3d94803..07cbe96 100644
--- a/fuse_sideload/fuse_sideload.cpp
+++ b/fuse_sideload/fuse_sideload.cpp
@@ -225,7 +225,7 @@
// 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 e239ddc..c591714 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -105,12 +105,9 @@
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 ee79a32..b12e529 100644
--- a/install/adb_install.cpp
+++ b/install/adb_install.cpp
@@ -90,11 +90,12 @@
// 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 @@
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 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 @@
"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 143b5d3..197e1de 100644
--- a/install/fuse_install.cpp
+++ b/install/fuse_install.cpp
@@ -146,10 +146,11 @@
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 @@
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 @@
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 63b116a..29c283f 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 bef23e9..0f5102f 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 @@
// 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 b34891f..42cad87 100644
--- a/install/include/install/wipe_data.h
+++ b/install/include/install/wipe_data.h
@@ -27,4 +27,4 @@
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 c60b999..903ddfd 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 6e74f80..83f3cad 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 @@
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 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 @@
} 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 @@
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 @@
}
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 @@
} 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 4eecf72..024c1e1 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* 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 @@
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 @@
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 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 915c87b..0a525fa 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 2bcfece..9d3f733 100644
--- a/minadbd/Android.bp
+++ b/minadbd/Android.bp
@@ -97,6 +97,7 @@
],
shared_libs: [
+ "android.hardware.health-V1-ndk", // from librecovery_utils
"libbase",
"libcrypto",
],
@@ -128,6 +129,7 @@
],
static_libs: [
+ "android.hardware.health-V1-ndk", // from librecovery_utils
"libminadbd_services",
"libfusesideload",
"librecovery_utils",
diff --git a/minadbd/OWNERS b/minadbd/OWNERS
new file mode 100644
index 0000000..8ee79dd
--- /dev/null
+++ b/minadbd/OWNERS
@@ -0,0 +1,2 @@
+enh@google.com
+shaju@google.com
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index 0abe867..16bcb5e 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -305,7 +305,7 @@
}
}
-asocket* daemon_service_to_socket(std::string_view) {
+asocket* daemon_service_to_socket(std::string_view, atransport*) {
return nullptr;
}
diff --git a/minui/Android.bp b/minui/Android.bp
index f68f6c8..02fb363 100644
--- a/minui/Android.bp
+++ b/minui/Android.bp
@@ -24,6 +24,7 @@
cc_library {
name: "libminui",
recovery_available: true,
+ vendor_available: true,
defaults: [
"recovery_defaults",
@@ -51,4 +52,15 @@
"libpng",
"libz",
],
+
+ target: {
+ vendor: {
+ exclude_static_libs: [
+ "libsync",
+ ],
+ shared_libs: [
+ "libsync",
+ ],
+ },
+ },
}
diff --git a/minui/events.cpp b/minui/events.cpp
index 863ac74..b307a49 100644
--- a/minui/events.cpp
+++ b/minui/events.cpp
@@ -267,6 +267,35 @@
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 dce1e61..597f2ce 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -42,6 +42,9 @@
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);
@@ -340,7 +343,22 @@
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") {
@@ -361,19 +379,22 @@
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 +450,10 @@
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 3c45a40..5408c93 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 @@
// 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 95759e3..c557022 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -105,6 +105,8 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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));
-
- /* 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 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;
+ 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;
}
}
- return main_monitor_connector;
+ /* If we didn't find a connector, grab the first one that is connected. */
+ if (drmConnectors.empty()) {
+ drmModeConnector* connector = find_first_connected_connector(fd, resources);
+ if (connector) {
+ drmConnectors.push_back(connector);
+ }
+ }
+
+ 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 drmConnectors.size() > 0;
}
void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
@@ -319,46 +363,49 @@
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");
+ if (!FindAndSetMonitor(drm_fd, res)) {
+ 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");
- drmModeFreeResources(res);
- close(drm_fd);
- return nullptr;
+ 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;
+ }
+
+ drm[i].monitor_crtc->mode = drm[i].monitor_connector->modes[drm[i].selected_mode];
+
+ int width = drm[i].monitor_crtc->mode.hdisplay;
+ int height = drm[i].monitor_crtc->mode.vdisplay;
+
+ 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;
+ }
+
+ drm[i].current_buffer = 0;
+ }
}
- DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
-
- main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
-
- int width = main_monitor_crtc->mode.hdisplay;
- int height = main_monitor_crtc->mode.vdisplay;
+ DisableNonMainCrtcs(drm_fd, res, drm[DRM_MAIN].monitor_crtc);
drmModeFreeResources(res);
- GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height);
- GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height);
- if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
- return nullptr;
- }
-
- current_buffer = 0;
-
// 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 @@
}
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 @@
}
}
- 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 57ba39b..fe3beaf 100644
--- a/minui/graphics_drm.h
+++ b/minui/graphics_drm.h
@@ -59,16 +59,23 @@
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);
- std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
- int current_buffer{ 0 };
- drmModeCrtc* main_monitor_crtc{ nullptr };
- drmModeConnector* main_monitor_connector{ nullptr };
+ 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];
+
int drm_fd{ -1 };
+ DrmConnector active_display = DRM_MAIN;
};
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 2584017..1cb0c0a 100644
--- a/minui/graphics_fbdev.cpp
+++ b/minui/graphics_fbdev.cpp
@@ -43,6 +43,10 @@
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 @@
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 596ba74..7e193c4 100644
--- a/minui/graphics_fbdev.h
+++ b/minui/graphics_fbdev.h
@@ -56,6 +56,7 @@
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 163e41d..a2f62f0 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -104,10 +104,19 @@
ARGB = 4,
};
-// 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 +127,7 @@
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 +162,7 @@
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 +170,7 @@
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/otautil/Android.bp b/otautil/Android.bp
index 557b8a3..4b043ad 100644
--- a/otautil/Android.bp
+++ b/otautil/Android.bp
@@ -34,16 +34,21 @@
// 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
similarity index 100%
rename from install/asn1_decoder.cpp
rename to otautil/asn1_decoder.cpp
diff --git a/install/include/install/package.h b/otautil/include/otautil/package.h
similarity index 98%
rename from install/include/install/package.h
rename to otautil/include/otautil/package.h
index 0b42332..f4f4d34 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
similarity index 100%
rename from install/include/install/verifier.h
rename to otautil/include/otautil/verifier.h
diff --git a/install/include/private/asn1_decoder.h b/otautil/include/private/asn1_decoder.h
similarity index 100%
rename from install/include/private/asn1_decoder.h
rename to otautil/include/private/asn1_decoder.h
diff --git a/install/package.cpp b/otautil/package.cpp
similarity index 99%
rename from install/package.cpp
rename to otautil/package.cpp
index 86fc064..242204e 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
similarity index 98%
rename from install/verifier.cpp
rename to otautil/verifier.cpp
index 3f02601..83ad708 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 @@
// 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 @@
} else {
LOG(INFO) << "Unknown key type " << key.key_type;
}
- i++;
}
if (need_sha1) {
@@ -310,13 +309,15 @@
}
static std::vector<Certificate> IterateZipEntriesAndSearchForKeys(const ZipArchiveHandle& handle) {
- void* cookie;
+ void* cookie{};
+
int32_t iter_status = StartIteration(handle, &cookie, "", "x509.pem");
if (iter_status != 0) {
LOG(ERROR) << "Failed to iterate over entries in the certificate zipfile: "
<< ErrorCodeString(iter_status);
return {};
}
+ std::unique_ptr<void, decltype(&EndIteration)> cookie_guard(cookie, &EndIteration);
std::vector<Certificate> result;
diff --git a/recovery-persist.cpp b/recovery-persist.cpp
index ad101ed..55699b2 100644
--- a/recovery-persist.cpp
+++ b/recovery-persist.cpp
@@ -77,6 +77,10 @@
}
}
+static bool file_exists(const char* filename) {
+ return access(filename, R_OK) == 0;
+}
+
static bool rotated = false;
ssize_t logsave(
@@ -141,7 +145,7 @@
if (has_cache) {
// Collects and reports the non-a/b update metrics from last_install; and removes the file
// to avoid duplicate report.
- if (access(LAST_INSTALL_FILE_IN_CACHE, F_OK) && unlink(LAST_INSTALL_FILE_IN_CACHE) == -1) {
+ if (file_exists(LAST_INSTALL_FILE_IN_CACHE) && unlink(LAST_INSTALL_FILE_IN_CACHE) == -1) {
PLOG(ERROR) << "Failed to unlink " << LAST_INSTALL_FILE_IN_CACHE;
}
@@ -152,9 +156,9 @@
}
}
- /* Is there something in pmsg? */
- if (access(LAST_PMSG_FILE, R_OK)) {
- return 0;
+ /* Is there something in pmsg? If not, no need to proceed. */
+ if (!file_exists(LAST_PMSG_FILE)) {
+ return 0;
}
// Take last pmsg file contents and send it off to the logsave
@@ -164,18 +168,18 @@
// For those device without /cache, the last_install file has been copied to
// /data/misc/recovery from pmsg. Looks for the sideload history only.
if (!has_cache) {
- if (access(LAST_INSTALL_FILE, F_OK) && unlink(LAST_INSTALL_FILE) == -1) {
+ if (file_exists(LAST_INSTALL_FILE) && unlink(LAST_INSTALL_FILE) == -1) {
PLOG(ERROR) << "Failed to unlink " << LAST_INSTALL_FILE;
}
}
/* Is there a last console log too? */
if (rotated) {
- if (!access(LAST_CONSOLE_FILE, R_OK)) {
- copy_file(LAST_CONSOLE_FILE, LAST_KMSG_FILE);
- } else if (!access(ALT_LAST_CONSOLE_FILE, R_OK)) {
- copy_file(ALT_LAST_CONSOLE_FILE, LAST_KMSG_FILE);
- }
+ if (file_exists(LAST_CONSOLE_FILE)) {
+ copy_file(LAST_CONSOLE_FILE, LAST_KMSG_FILE);
+ } else if (file_exists(ALT_LAST_CONSOLE_FILE)) {
+ copy_file(ALT_LAST_CONSOLE_FILE, LAST_KMSG_FILE);
+ }
}
return 0;
diff --git a/recovery.cpp b/recovery.cpp
index 36924fb..4d39019 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 @@
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 @@
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 @@
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 @@
} 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 80cba61..9a358ab 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -73,12 +73,12 @@
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 d79f41d..0318db8 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 @@
}
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 @@
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 ea710ab..3aadea2 100644
--- a/recovery_ui/include/recovery_ui/ethernet_device.h
+++ b/recovery_ui/include/recovery_ui/ethernet_device.h
@@ -27,6 +27,7 @@
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 @@
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 e0e9ec0..9bd66c5 100644
--- a/recovery_utils/Android.bp
+++ b/recovery_utils/Android.bp
@@ -31,6 +31,7 @@
shared_libs: [
"android.hardware.health@2.0",
"libbase",
+ "libbinder_ndk",
"libext4_utils",
"libfs_mgr",
"libhidlbase",
@@ -42,8 +43,10 @@
"libotautil",
// External dependencies.
+ "android.hardware.health-translate-ndk",
"libfstab",
"libhealthhalutils",
+ "libhealthshim",
],
}
@@ -70,6 +73,15 @@
"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 323f525..6b126bd 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 @@
}
// 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 1948447..5c95cba 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 @@
}
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 @@
"-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 5ef4d58..9ad3d3b 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -134,11 +134,22 @@
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 @@
"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 baa44e0..36c8534 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 fb12178..1603982 100644
--- a/tests/unit/host/update_simulator_test.cpp
+++ b/tests/unit/host/update_simulator_test.cpp
@@ -101,7 +101,7 @@
// 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 @@
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 @@
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 @@
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, RunUpdateSmoke) {
+TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateSmoke) {
string recovery_img_string = "recovery.img";
string boot_img_string = "boot.img";
@@ -326,7 +326,7 @@
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 @@
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 164a93d..66882bb 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 ded23c5..08a3ddf 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 45fcd15..67dca2a 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/tools/recovery_l10n/res/values-nb/strings.xml b/tools/recovery_l10n/res/values-nb/strings.xml
index e8cad13..61d1173 100644
--- a/tools/recovery_l10n/res/values-nb/strings.xml
+++ b/tools/recovery_l10n/res/values-nb/strings.xml
@@ -7,7 +7,7 @@
<string name="recovery_error" msgid="5748178989622716736">"Feil!"</string>
<string name="recovery_installing_security" msgid="9184031299717114342">"Installerer sikkerhetsoppdateringen"</string>
<string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Kan ikke laste inn Android-systemet. Dataene dine er muligens skadet. Hvis du fortsetter å se denne meldingen, må du muligens tilbakestille til fabrikkstandard og tømme alle brukerdataene som er lagret på denne enheten."</string>
- <string name="recovery_try_again" msgid="7168248750158873496">"Prøv igjen"</string>
+ <string name="recovery_try_again" msgid="7168248750158873496">"Prøv på nytt"</string>
<string name="recovery_factory_data_reset" msgid="7321351565602894783">"Tilbakestill til fabrikkstandard"</string>
<string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Vil du viske ut alle brukerdataene?\n\n DETTE KAN IKKE ANGRES!"</string>
<string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Avbryt"</string>
diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml
index 38ca612..5747075 100644
--- a/tools/recovery_l10n/res/values-te/strings.xml
+++ b/tools/recovery_l10n/res/values-te/strings.xml
@@ -10,5 +10,5 @@
<string name="recovery_try_again" msgid="7168248750158873496">"మళ్లీ ప్రయత్నించు"</string>
<string name="recovery_factory_data_reset" msgid="7321351565602894783">"ఫ్యాక్టరీ డేటా రీసెట్"</string>
<string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"వినియోగదారు డేటా మొత్తాన్ని తొలగించాలా?\n\n ఈ చర్యను రద్దు చేయలేరు!"</string>
- <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయి"</string>
+ <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయండి"</string>
</resources>
diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp
index ff2eff9..cb97bd1 100644
--- a/update_verifier/Android.bp
+++ b/update_verifier/Android.bp
@@ -33,6 +33,25 @@
],
}
+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",
@@ -54,6 +73,10 @@
"libvold_binder",
],
+ whole_static_libs: [
+ "libsnapshot_snapuserd",
+ ],
+
shared_libs: [
"android.hardware.boot@1.0",
"libbase",
diff --git a/update_verifier/care_map_generator.py b/update_verifier/care_map_generator.py
index c6f2dad..b1396a4 100644
--- a/update_verifier/care_map_generator.py
+++ b/update_verifier/care_map_generator.py
@@ -111,14 +111,14 @@
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:
diff --git a/update_verifier/include/update_verifier/update_verifier.h b/update_verifier/include/update_verifier/update_verifier.h
index 4c64b1e..0cccc90 100644
--- a/update_verifier/include/update_verifier/update_verifier.h
+++ b/update_verifier/include/update_verifier/update_verifier.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <snapuserd/snapuserd_client.h>
#include "otautil/rangeset.h"
// The update verifier performs verification upon the first boot to a new slot on A/B devices.
@@ -68,4 +69,8 @@
// The function to read the device property; default value: android::base::GetProperty()
std::function<std::string(const std::string&)> property_reader_;
+
+ // Check if snapuserd daemon has already completed the update verification
+ // Applicable only for VABC with userspace snapshots
+ bool CheckVerificationStatus();
};
diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
index a042f90..88fcfa5 100644
--- a/update_verifier/update_verifier.cpp
+++ b/update_verifier/update_verifier.cpp
@@ -52,6 +52,7 @@
#include <future>
#include <thread>
+#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
@@ -188,7 +189,28 @@
return ret;
}
+bool UpdateVerifier::CheckVerificationStatus() {
+ auto client =
+ android::snapshot::SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 5s);
+ if (!client) {
+ LOG(ERROR) << "Unable to connect to snapuserd";
+ return false;
+ }
+
+ return client->QueryUpdateVerification();
+}
+
bool UpdateVerifier::VerifyPartitions() {
+ const bool userspace_snapshots =
+ android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
+
+ if (userspace_snapshots && CheckVerificationStatus()) {
+ LOG(INFO) << "Partitions verified by snapuserd daemon";
+ return true;
+ }
+
+ LOG(INFO) << "Partitions not verified by snapuserd daemon";
+
auto dm_block_devices = FindDmPartitions();
if (dm_block_devices.empty()) {
LOG(ERROR) << "No dm-enabled block device is found.";