summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--Android.mk10
-rw-r--r--METADATA6
-rw-r--r--OWNERS3
-rw-r--r--PREUPLOAD.cfg1
-rw-r--r--bootloader_message/bootloader_message.cpp10
-rw-r--r--bootloader_message/include/bootloader_message/bootloader_message.h20
-rw-r--r--edify/parser.yy1
-rw-r--r--etc/init.rc12
-rw-r--r--fuse_sideload/fuse_provider.cpp9
-rw-r--r--fuse_sideload/fuse_sideload.cpp2
-rw-r--r--install/Android.bp3
-rw-r--r--install/adb_install.cpp9
-rw-r--r--install/fuse_install.cpp9
-rw-r--r--install/include/install/fuse_install.h2
-rw-r--r--install/include/install/install.h6
-rw-r--r--install/include/install/wipe_data.h2
-rw-r--r--install/include/install/wipe_device.h2
-rw-r--r--install/install.cpp55
-rw-r--r--install/wipe_data.cpp38
-rw-r--r--install/wipe_device.cpp2
-rw-r--r--minadbd/Android.bp2
-rw-r--r--minui/Android.bp12
-rw-r--r--minui/events.cpp29
-rw-r--r--minui/graphics.cpp39
-rw-r--r--minui/graphics.h11
-rw-r--r--minui/graphics_drm.cpp189
-rw-r--r--minui/graphics_drm.h19
-rw-r--r--minui/graphics_fbdev.cpp6
-rw-r--r--minui/graphics_fbdev.h1
-rw-r--r--minui/include/minui/minui.h18
-rw-r--r--otautil/Android.bp5
-rw-r--r--otautil/asn1_decoder.cpp (renamed from install/asn1_decoder.cpp)0
-rw-r--r--otautil/include/otautil/package.h (renamed from install/include/install/package.h)2
-rw-r--r--otautil/include/otautil/verifier.h (renamed from install/include/install/verifier.h)0
-rw-r--r--otautil/include/private/asn1_decoder.h (renamed from install/include/private/asn1_decoder.h)0
-rw-r--r--otautil/package.cpp (renamed from install/package.cpp)2
-rw-r--r--otautil/verifier.cpp (renamed from install/verifier.cpp)7
-rw-r--r--recovery.cpp18
-rw-r--r--recovery_ui/ethernet_device.cpp12
-rw-r--r--recovery_ui/include/recovery_ui/ethernet_device.h3
-rw-r--r--recovery_utils/Android.bp12
-rw-r--r--recovery_utils/battery_utils.cpp73
-rw-r--r--recovery_utils/roots.cpp57
-rw-r--r--tests/Android.bp15
-rw-r--r--tests/fuzz/verify_package_fuzzer.cpp2
-rw-r--r--tests/unit/host/update_simulator_test.cpp14
-rw-r--r--tests/unit/package_test.cpp2
-rw-r--r--tests/unit/verifier_test.cpp4
-rw-r--r--tools/recovery_l10n/res/values-as/strings.xml4
-rw-r--r--tools/recovery_l10n/res/values-kn/strings.xml2
-rw-r--r--tools/recovery_l10n/res/values-sv/strings.xml2
-rw-r--r--tools/recovery_l10n/res/values-te/strings.xml8
-rw-r--r--update_verifier/Android.bp19
-rw-r--r--update_verifier/care_map_generator.py4
55 files changed, 542 insertions, 254 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
diff --git a/METADATA b/METADATA
index a1ce3c66a..68bf6f8bb 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 79dd9f776..45c72e380 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 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/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..597f2ceaf 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -42,6 +42,9 @@ static constexpr uint32_t alpha_mask = 0xff000000;
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 @@ 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") {
@@ -361,19 +379,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 +450,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..a2f62f0a6 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -104,10 +104,19 @@ enum class PixelFormat : int {
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 @@ 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 +162,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 +170,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/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_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-as/strings.xml b/tools/recovery_l10n/res/values-as/strings.xml
index d956b9a3b..33a204d05 100644
--- a/tools/recovery_l10n/res/values-as/strings.xml
+++ b/tools/recovery_l10n/res/values-as/strings.xml
@@ -6,9 +6,9 @@
<string name="recovery_no_command" msgid="4465476568623024327">"কোনো আদেশ নাই"</string>
<string name="recovery_error" msgid="5748178989622716736">"ত্ৰুটি!"</string>
<string name="recovery_installing_security" msgid="9184031299717114342">"সুৰক্ষা আপডেইট ইনষ্টল কৰি থকা হৈছে"</string>
- <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android ছিষ্টেম ল\'ড কৰিব নোৱাৰি। আপোনাৰ ডেটাত কিবা আসোঁৱাহ থকা যেন লাগিছে। আপুনি যদি এই বাৰ্তাটো পায়েই থাকে, আপুনি নিজৰ ডিভাইচটো ফেক্টৰী ডেটা ৰিছেট কৰি সেইটোত থকা ব্যৱহাৰকাৰীৰ আটাইবোৰ ডেটা মচিব লগা হ\'ব পাৰে।"</string>
+ <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android ছিষ্টেম ল\'ড কৰিব নোৱাৰি। আপোনাৰ ডেটাত কিবা আসোঁৱাহ থকা যেন লাগিছে। আপুনি যদি এই বাৰ্তাটো পায়েই থাকে, আপুনি নিজৰ ডিভাইচটো ফেক্টৰী ডেটা ৰিছেট কৰি সেইটোত থকা ব্যৱহাৰকাৰীৰ সকলো ডেটা মচিব লগা হ\'ব পাৰে।"</string>
<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_wipe_data_confirmation" msgid="5439823343348043954">"ব্যৱহাৰকাৰীৰ সকলো ডেটা মচিবনে?\n\n এইটো কৰাৰ পিছত আনডু কৰিব নোৱাৰি!"</string>
<string name="recovery_cancel_wipe_data" msgid="66987687653647384">"বাতিল কৰক"</string>
</resources>
diff --git a/tools/recovery_l10n/res/values-kn/strings.xml b/tools/recovery_l10n/res/values-kn/strings.xml
index eafd831e7..a98f4692a 100644
--- a/tools/recovery_l10n/res/values-kn/strings.xml
+++ b/tools/recovery_l10n/res/values-kn/strings.xml
@@ -8,7 +8,7 @@
<string name="recovery_installing_security" msgid="9184031299717114342">"ಭದ್ರತೆಯ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android ಸಿಸ್ಟಂ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಡೇಟಾ ದೋಷಪೂರಿತವಾಗಿರಬಹುದು. ನೀವು ಈ ಸಂದೇಶ ಪಡೆಯುವುದು ಮುಂದುವರಿದರೆ, ನೀವು ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರಿಸೆಟ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ ಮತ್ತು ಈ ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾದ ಎಲ್ಲಾ ಬಳಕೆದಾರರ ಡೇಟಾವನ್ನು ಅಳಿಸಬೇಕಾಗುತ್ತದೆ."</string>
<string name="recovery_try_again" msgid="7168248750158873496">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
- <string name="recovery_factory_data_reset" msgid="7321351565602894783">"ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರೀಸೆಟ್"</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>
</resources>
diff --git a/tools/recovery_l10n/res/values-sv/strings.xml b/tools/recovery_l10n/res/values-sv/strings.xml
index baf8e1830..cf43b2511 100644
--- a/tools/recovery_l10n/res/values-sv/strings.xml
+++ b/tools/recovery_l10n/res/values-sv/strings.xml
@@ -2,7 +2,7 @@
<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">"Systemuppdatering installeras"</string>
- <string name="recovery_erasing" msgid="7334826894904037088">"Raderar"</string>
+ <string name="recovery_erasing" msgid="7334826894904037088">"Rensar"</string>
<string name="recovery_no_command" msgid="4465476568623024327">"Inget kommando"</string>
<string name="recovery_error" msgid="5748178989622716736">"Fel!"</string>
<string name="recovery_installing_security" msgid="9184031299717114342">"Säkerhetsuppdatering installeras"</string>
diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml
index 38ca6127d..4d521143f 100644
--- a/tools/recovery_l10n/res/values-te/strings.xml
+++ b/tools/recovery_l10n/res/values-te/strings.xml
@@ -1,12 +1,12 @@
<?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>
- <string name="recovery_installing_security" msgid="9184031299717114342">"సెక్యూరిటీ అప్‌డేట్‌ను ఇన్‌స్టాల్ చేస్తోంది"</string>
- <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android సిస్టమ్‌ని లోడ్ చేయడం సాధ్యం కాదు. మీ డేటా పాడై ఉండవచ్చు. మీకు ఈ మెసేజ్‌ వస్తూనే ఉంటే, మీరు ఫ్యాక్టరీ డేటా రీసెట్ చేసి, పరికరంలో నిల్వ అయిన వినియోగదారు డేటా మొత్తాన్ని తొలగించాల్సి రావచ్చు."</string>
+ <string name="recovery_error" msgid="5748178989622716736">"ఎర్రర్ సంభవించింది!"</string>
+ <string name="recovery_installing_security" msgid="9184031299717114342">"భద్రతా నవీకరణను ఇన్‌స్టాల్ చేస్తోంది"</string>
+ <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android సిస్టమ్‌ని లోడ్ చేయడం సాధ్యం కాదు. మీ డేటా పాడై ఉండవచ్చు. మీకు ఈ సందేశం వస్తూనే ఉంటే, మీరు ఫ్యాక్టరీ డేటా రీసెట్ చేసి, పరికరంలో నిల్వ అయిన వినియోగదారు డేటా మొత్తాన్ని తొలగించాల్సి రావచ్చు."</string>
<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>
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: