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--minadbd/minadbd.cpp1
-rw-r--r--minui/Android.bp12
-rw-r--r--minui/events.cpp29
-rw-r--r--minui/graphics.cpp94
-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.h19
-rw-r--r--minui/resources.cpp56
-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_main.cpp10
-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--update_verifier/Android.bp19
-rw-r--r--update_verifier/care_map_generator.py4
54 files changed, 631 insertions, 272 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/minadbd/minadbd.cpp b/minadbd/minadbd.cpp
index 7b82faa05..1df342c87 100644
--- a/minadbd/minadbd.cpp
+++ b/minadbd/minadbd.cpp
@@ -64,6 +64,7 @@ int main(int argc, char** argv) {
// We can't require authentication for sideloading. http://b/22025550.
auth_required = false;
+ socket_access_allowed = false;
init_transport_registration();
usb_init();
diff --git a/minui/Android.bp b/minui/Android.bp
index f68f6c81d..02fb3638f 100644
--- a/minui/Android.bp
+++ b/minui/Android.bp
@@ -24,6 +24,7 @@ package {
cc_library {
name: "libminui",
recovery_available: true,
+ vendor_available: true,
defaults: [
"recovery_defaults",
@@ -51,4 +52,15 @@ cc_library {
"libpng",
"libz",
],
+
+ target: {
+ vendor: {
+ exclude_static_libs: [
+ "libsync",
+ ],
+ shared_libs: [
+ "libsync",
+ ],
+ },
+ },
}
diff --git a/minui/events.cpp b/minui/events.cpp
index 863ac7474..b307a4977 100644
--- a/minui/events.cpp
+++ b/minui/events.cpp
@@ -267,6 +267,35 @@ int ev_get_input(int fd, uint32_t epevents, input_event* ev) {
return -1;
}
+int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb) {
+ // Use unsigned long to match ioctl's parameter type.
+ unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
+ unsigned long sw_bits[BITS_TO_LONGS(SW_MAX)]; // NOLINT
+
+ for (size_t i = 0; i < g_ev_dev_count; ++i) {
+ memset(ev_bits, 0, sizeof(ev_bits));
+ memset(sw_bits, 0, sizeof(sw_bits));
+
+ if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
+ continue;
+ }
+ if (!test_bit(EV_SW, ev_bits)) {
+ continue;
+ }
+ if (ioctl(ev_fdinfo[i].fd, EVIOCGSW(sizeof(sw_bits)), sw_bits) == -1) {
+ continue;
+ }
+
+ for (int code = 0; code <= SW_MAX; code++) {
+ if (test_bit(code, sw_bits)) {
+ set_sw_cb(code, 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
int ev_sync_key_state(const ev_set_key_callback& set_key_cb) {
// Use unsigned long to match ioctl's parameter type.
unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index dce1e619a..b24c2b114 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -36,12 +36,14 @@ static int overscan_offset_x = 0;
static int overscan_offset_y = 0;
static uint32_t gr_current = ~0;
-static constexpr uint32_t alpha_mask = 0xff000000;
// gr_draw is owned by backends.
static GRSurface* gr_draw = nullptr;
static GRRotation rotation = GRRotation::NONE;
static PixelFormat pixel_format = PixelFormat::UNKNOWN;
+// The graphics backend list that provides fallback options for the default backend selection.
+// For example, it will fist try DRM, then try FBDEV if DRM is unavailable.
+constexpr auto default_backends = { GraphicsBackend::DRM, GraphicsBackend::FBDEV };
static bool outside(int x, int y) {
auto swapped = (rotation == GRRotation::LEFT || rotation == GRRotation::RIGHT);
@@ -76,7 +78,7 @@ int gr_font_size(const GRFont* font, int* x, int* y) {
}
// Blends gr_current onto pix value, assumes alpha as most significant byte.
-static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) {
+static inline uint32_t pixel_blend_argb(uint8_t alpha, uint32_t pix) {
if (alpha == 255) return gr_current;
if (alpha == 0) return pix;
uint32_t pix_r = pix & 0xff;
@@ -93,6 +95,48 @@ static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) {
return (out_r & 0xff) | (out_g & 0xff00) | (out_b & 0xff0000) | (gr_current & 0xff000000);
}
+static inline uint32_t pixel_blend_rgba(uint8_t alpha, uint32_t pix) {
+ if (alpha == 255) return gr_current;
+ if (alpha == 0) return pix;
+ uint32_t pix_r = pix & 0xff00;
+ uint32_t pix_g = pix & 0xff0000;
+ uint32_t pix_b = pix & 0xff000000;
+ uint32_t cur_r = gr_current & 0xff00;
+ uint32_t cur_g = gr_current & 0xff0000;
+ uint32_t cur_b = gr_current & 0xff000000;
+
+ uint32_t out_r = (pix_r * (255 - alpha) + cur_r * alpha) / 255;
+ uint32_t out_g = (pix_g * (255 - alpha) + cur_g * alpha) / 255;
+ uint32_t out_b = (pix_b * (255 - alpha) + cur_b * alpha) / 255;
+
+ return (gr_current & 0xff) | (out_r & 0xff00) | (out_g & 0xff0000) | (out_b & 0xff000000);
+}
+
+static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) {
+ if (pixel_format == PixelFormat::RGBA) {
+ return pixel_blend_rgba(alpha, pix);
+ }
+ return pixel_blend_argb(alpha, pix);
+}
+
+static inline uint32_t get_alphamask() {
+ if (pixel_format == PixelFormat::RGBA) {
+ return 0x000000ff;
+ }
+ return 0xff000000;
+}
+
+static inline uint8_t get_alpha_shift() {
+ if (pixel_format == PixelFormat::RGBA) {
+ return 0;
+ }
+ return 24;
+}
+
+static inline uint8_t get_alpha(uint32_t pix) {
+ return static_cast<uint8_t>((pix & (gr_current & get_alphamask())) >> get_alpha_shift());
+}
+
// Increments pixel pointer right, with current rotation.
static void incr_x(uint32_t** p, int row_pixels) {
if (rotation == GRRotation::LEFT) {
@@ -140,7 +184,7 @@ static uint32_t* PixelAt(GRSurface* surface, int x, int y, int row_pixels) {
static void TextBlend(const uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, int dst_row_pixels,
int width, int height) {
- uint8_t alpha_current = static_cast<uint8_t>((alpha_mask & gr_current) >> 24);
+ uint8_t alpha_current = get_alpha(gr_current);
for (int j = 0; j < height; ++j) {
const uint8_t* sx = src_p;
uint32_t* px = dst_p;
@@ -155,7 +199,7 @@ static void TextBlend(const uint8_t* src_p, int src_row_bytes, uint32_t* dst_p,
}
void gr_text(const GRFont* font, int x, int y, const char* s, bool bold) {
- if (!font || !font->texture || (gr_current & alpha_mask) == 0) return;
+ if (!font || !font->texture || (gr_current & get_alphamask()) == 0) return;
if (font->texture->pixel_bytes != 1) {
printf("gr_text: font has wrong format\n");
@@ -210,6 +254,8 @@ void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a
uint32_t r32 = r, g32 = g, b32 = b, a32 = a;
if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) {
gr_current = (a32 << 24) | (r32 << 16) | (g32 << 8) | b32;
+ } else if (pixel_format == PixelFormat::RGBA) {
+ gr_current = (b32 << 24) | (g32 << 16) | (r32 << 8) | a32;
} else {
gr_current = (a32 << 24) | (b32 << 16) | (g32 << 8) | r32;
}
@@ -244,7 +290,7 @@ void gr_fill(int x1, int y1, int x2, int y2) {
int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
uint32_t* p = PixelAt(gr_draw, x1, y1, row_pixels);
- uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24));
+ uint8_t alpha = get_alpha(gr_current);
if (alpha > 0) {
for (int y = y1; y < y2; ++y) {
uint32_t* px = p;
@@ -340,7 +386,22 @@ void gr_flip() {
gr_draw = gr_backend->Flip();
}
+std::unique_ptr<MinuiBackend> create_backend(GraphicsBackend backend) {
+ switch (backend) {
+ case GraphicsBackend::DRM:
+ return std::make_unique<MinuiBackendDrm>();
+ case GraphicsBackend::FBDEV:
+ return std::make_unique<MinuiBackendFbdev>();
+ default:
+ return nullptr;
+ }
+}
+
int gr_init() {
+ return gr_init(default_backends);
+}
+
+int gr_init(std::initializer_list<GraphicsBackend> backends) {
// pixel_format needs to be set before loading any resources or initializing backends.
std::string format = android::base::GetProperty("ro.minui.pixel_format", "");
if (format == "ABGR_8888") {
@@ -351,6 +412,8 @@ int gr_init() {
pixel_format = PixelFormat::ARGB;
} else if (format == "BGRA_8888") {
pixel_format = PixelFormat::BGRA;
+ } else if (format == "RGBA_8888") {
+ pixel_format = PixelFormat::RGBA;
} else {
pixel_format = PixelFormat::UNKNOWN;
}
@@ -361,19 +424,22 @@ int gr_init() {
ret);
}
- auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendDrm>() };
- gr_draw = backend->Init();
-
- if (!gr_draw) {
- backend = std::make_unique<MinuiBackendFbdev>();
- gr_draw = backend->Init();
+ std::unique_ptr<MinuiBackend> minui_backend;
+ for (GraphicsBackend backend : backends) {
+ minui_backend = create_backend(backend);
+ if (!minui_backend) {
+ printf("gr_init: minui_backend %d is a nullptr\n", backend);
+ continue;
+ }
+ gr_draw = minui_backend->Init();
+ if (gr_draw) break;
}
if (!gr_draw) {
return -1;
}
- gr_backend = backend.release();
+ gr_backend = minui_backend.release();
int overscan_percent = android::base::GetIntProperty("ro.minui.overscan_percent", 0);
overscan_offset_x = gr_draw->width * overscan_percent / 100;
@@ -429,6 +495,10 @@ void gr_fb_blank(bool blank) {
gr_backend->Blank(blank);
}
+void gr_fb_blank(bool blank, int index) {
+ gr_backend->Blank(blank, static_cast<MinuiBackend::DrmConnector>(index));
+}
+
void gr_rotate(GRRotation rot) {
rotation = rot;
}
diff --git a/minui/graphics.h b/minui/graphics.h
index 3c45a406b..5408c93e9 100644
--- a/minui/graphics.h
+++ b/minui/graphics.h
@@ -21,6 +21,12 @@
class MinuiBackend {
public:
+ enum DrmConnector {
+ DRM_MAIN = 0,
+ DRM_SEC,
+ DRM_MAX,
+ };
+
// Initializes the backend and returns a GRSurface* to draw into.
virtual GRSurface* Init() = 0;
@@ -28,9 +34,12 @@ class MinuiBackend {
// be displayed, and returns a new drawing surface.
virtual GRSurface* Flip() = 0;
- // Blank (or unblank) the screen.
+ // Blank (or unblank) the default screen.
virtual void Blank(bool) = 0;
+ // Blank (or unblank) the specific screen.
+ virtual void Blank(bool blank, DrmConnector index) = 0;
+
// Device cleanup when drawing is done.
virtual ~MinuiBackend() {};
};
diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp
index 95759e382..c55702276 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -105,6 +105,8 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he
perror("Failed to DRM_IOCTL_MODE_CREATE_DUMB");
return nullptr;
}
+ printf("Allocating buffer with resolution %d x %d pitch: %d bpp: %d, size: %llu\n", width, height,
+ create_dumb.pitch, create_dumb.bpp, create_dumb.size);
// Cannot use std::make_unique to access non-public ctor.
auto surface = std::unique_ptr<GRSurfaceDrm>(new GRSurfaceDrm(
@@ -128,13 +130,14 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he
return nullptr;
}
- auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE,
- MAP_SHARED, drm_fd, map_dumb.offset);
+ auto mmapped =
+ mmap(nullptr, create_dumb.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, map_dumb.offset);
if (mmapped == MAP_FAILED) {
perror("Failed to mmap()");
return nullptr;
}
surface->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
+ printf("Framebuffer of size %llu allocated @ %p\n", create_dumb.size, surface->mmapped_buffer_);
return surface;
}
@@ -150,22 +153,50 @@ void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) {
}
bool MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc,
- const std::unique_ptr<GRSurfaceDrm>& surface) {
+ const std::unique_ptr<GRSurfaceDrm>& surface,
+ uint32_t* connector_id) {
if (drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y
- &main_monitor_connector->connector_id,
- 1, // connector_count
- &main_monitor_crtc->mode) != 0) {
- perror("Failed to drmModeSetCrtc");
+ connector_id, 1, // connector_count
+ &crtc->mode) != 0) {
+ fprintf(stderr, "Failed to drmModeSetCrtc(%d)\n", *connector_id);
return false;
}
+
return true;
}
void MinuiBackendDrm::Blank(bool blank) {
+ Blank(blank, DRM_MAIN);
+}
+
+void MinuiBackendDrm::Blank(bool blank, DrmConnector index) {
+ const auto* drmInterface = &drm[DRM_MAIN];
+
+ switch (index) {
+ case DRM_MAIN:
+ drmInterface = &drm[DRM_MAIN];
+ break;
+ case DRM_SEC:
+ drmInterface = &drm[DRM_SEC];
+ break;
+ default:
+ fprintf(stderr, "Invalid index: %d\n", index);
+ return;
+ }
+
+ if (!drmInterface->monitor_connector) {
+ fprintf(stderr, "Unsupported. index = %d\n", index);
+ return;
+ }
+
if (blank) {
- DrmDisableCrtc(drm_fd, main_monitor_crtc);
+ DrmDisableCrtc(drm_fd, drmInterface->monitor_crtc);
} else {
- DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]);
+ DrmEnableCrtc(drm_fd, drmInterface->monitor_crtc,
+ drmInterface->GRSurfaceDrms[drmInterface->current_buffer],
+ &drmInterface->monitor_connector->connector_id);
+
+ active_display = index;
}
}
@@ -207,18 +238,21 @@ static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources,
return nullptr;
}
-static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) {
+std::vector<drmModeConnector*> find_used_connector_by_type(int fd, drmModeRes* resources,
+ unsigned type) {
+ std::vector<drmModeConnector*> drmConnectors;
for (int i = 0; i < resources->count_connectors; i++) {
drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
if (connector) {
if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) &&
(connector->count_modes > 0)) {
- return connector;
+ drmConnectors.push_back(connector);
+ } else {
+ drmModeFreeConnector(connector);
}
- drmModeFreeConnector(connector);
}
}
- return nullptr;
+ return drmConnectors;
}
static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) {
@@ -236,8 +270,7 @@ static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* reso
return nullptr;
}
-drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources,
- uint32_t* mode_index) {
+bool MinuiBackendDrm::FindAndSetMonitor(int fd, drmModeRes* resources) {
/* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
static constexpr unsigned kConnectorPriority[] = {
DRM_MODE_CONNECTOR_LVDS,
@@ -245,30 +278,41 @@ drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources
DRM_MODE_CONNECTOR_DSI,
};
- drmModeConnector* main_monitor_connector = nullptr;
- unsigned i = 0;
- do {
- main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
- i++;
- } while (!main_monitor_connector && i < arraysize(kConnectorPriority));
+ std::vector<drmModeConnector*> drmConnectors;
+ for (int i = 0; i < arraysize(kConnectorPriority) && drmConnectors.size() < DRM_MAX; i++) {
+ auto connectors = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
+ for (auto connector : connectors) {
+ drmConnectors.push_back(connector);
+ if (drmConnectors.size() >= DRM_MAX) break;
+ }
+ }
/* If we didn't find a connector, grab the first one that is connected. */
- if (!main_monitor_connector) {
- main_monitor_connector = find_first_connected_connector(fd, resources);
+ if (drmConnectors.empty()) {
+ drmModeConnector* connector = find_first_connected_connector(fd, resources);
+ if (connector) {
+ drmConnectors.push_back(connector);
+ }
}
- /* If we still didn't find a connector, give up and return. */
- if (!main_monitor_connector) return nullptr;
-
- *mode_index = 0;
- for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
- if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
- *mode_index = modes;
- break;
+ for (int drm_index = 0; drm_index < drmConnectors.size(); drm_index++) {
+ drm[drm_index].monitor_connector = drmConnectors[drm_index];
+
+ drm[drm_index].selected_mode = 0;
+ for (int modes = 0; modes < drmConnectors[drm_index]->count_modes; modes++) {
+ printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes,
+ drmConnectors[drm_index]->modes[modes].hdisplay,
+ drmConnectors[drm_index]->modes[modes].vdisplay,
+ drmConnectors[drm_index]->modes[modes].vrefresh);
+ if (drmConnectors[drm_index]->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
+ printf("Choosing display mode #%d\n", modes);
+ drm[drm_index].selected_mode = modes;
+ break;
+ }
}
}
- return main_monitor_connector;
+ return drmConnectors.size() > 0;
}
void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
@@ -319,46 +363,49 @@ GRSurface* MinuiBackendDrm::Init() {
return nullptr;
}
- uint32_t selected_mode;
- main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode);
- if (!main_monitor_connector) {
- fprintf(stderr, "Failed to find main_monitor_connector\n");
- drmModeFreeResources(res);
- close(drm_fd);
- return nullptr;
- }
-
- main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
- if (!main_monitor_crtc) {
- fprintf(stderr, "Failed to find main_monitor_crtc\n");
+ if (!FindAndSetMonitor(drm_fd, res)) {
+ fprintf(stderr, "Failed to find main monitor_connector\n");
drmModeFreeResources(res);
- close(drm_fd);
return nullptr;
}
- DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
+ for (int i = 0; i < DRM_MAX; i++) {
+ if (drm[i].monitor_connector) {
+ drm[i].monitor_crtc = find_crtc_for_connector(drm_fd, res, drm[i].monitor_connector);
+ if (!drm[i].monitor_crtc) {
+ fprintf(stderr, "Failed to find monitor_crtc, drm index=%d\n", i);
+ drmModeFreeResources(res);
+ return nullptr;
+ }
- main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
+ drm[i].monitor_crtc->mode = drm[i].monitor_connector->modes[drm[i].selected_mode];
- int width = main_monitor_crtc->mode.hdisplay;
- int height = main_monitor_crtc->mode.vdisplay;
+ int width = drm[i].monitor_crtc->mode.hdisplay;
+ int height = drm[i].monitor_crtc->mode.vdisplay;
- drmModeFreeResources(res);
+ drm[i].GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height);
+ drm[i].GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height);
+ if (!drm[i].GRSurfaceDrms[0] || !drm[i].GRSurfaceDrms[1]) {
+ fprintf(stderr, "Failed to create GRSurfaceDrm, drm index=%d\n", i);
+ drmModeFreeResources(res);
+ return nullptr;
+ }
- GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height);
- GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height);
- if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
- return nullptr;
+ drm[i].current_buffer = 0;
+ }
}
- current_buffer = 0;
+ DisableNonMainCrtcs(drm_fd, res, drm[DRM_MAIN].monitor_crtc);
+
+ drmModeFreeResources(res);
// We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
- if (!DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1])) {
+ if (!DrmEnableCrtc(drm_fd, drm[DRM_MAIN].monitor_crtc, drm[DRM_MAIN].GRSurfaceDrms[1],
+ &drm[DRM_MAIN].monitor_connector->connector_id)) {
return nullptr;
}
- return GRSurfaceDrms[0].get();
+ return drm[DRM_MAIN].GRSurfaceDrms[0].get();
}
static void page_flip_complete(__unused int fd,
@@ -370,10 +417,19 @@ static void page_flip_complete(__unused int fd,
}
GRSurface* MinuiBackendDrm::Flip() {
+ GRSurface* surface = NULL;
+ DrmInterface* current_drm = &drm[active_display];
bool ongoing_flip = true;
- if (drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, GRSurfaceDrms[current_buffer]->fb_id,
+
+ if (!current_drm->monitor_connector) {
+ fprintf(stderr, "Unsupported. active_display = %d\n", active_display);
+ return nullptr;
+ }
+
+ if (drmModePageFlip(drm_fd, current_drm->monitor_crtc->crtc_id,
+ current_drm->GRSurfaceDrms[current_drm->current_buffer]->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip) != 0) {
- perror("Failed to drmModePageFlip");
+ fprintf(stderr, "Failed to drmModePageFlip, active_display=%d", active_display);
return nullptr;
}
@@ -399,14 +455,19 @@ GRSurface* MinuiBackendDrm::Flip() {
}
}
- current_buffer = 1 - current_buffer;
- return GRSurfaceDrms[current_buffer].get();
+ current_drm->current_buffer = 1 - current_drm->current_buffer;
+ surface = current_drm->GRSurfaceDrms[current_drm->current_buffer].get();
+ return surface;
}
MinuiBackendDrm::~MinuiBackendDrm() {
- DrmDisableCrtc(drm_fd, main_monitor_crtc);
- drmModeFreeCrtc(main_monitor_crtc);
- drmModeFreeConnector(main_monitor_connector);
+ for (int i = 0; i < DRM_MAX; i++) {
+ if (drm[i].monitor_connector) {
+ DrmDisableCrtc(drm_fd, drm[i].monitor_crtc);
+ drmModeFreeCrtc(drm[i].monitor_crtc);
+ drmModeFreeConnector(drm[i].monitor_connector);
+ }
+ }
close(drm_fd);
drm_fd = -1;
}
diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h
index 57ba39b83..fe3beaff9 100644
--- a/minui/graphics_drm.h
+++ b/minui/graphics_drm.h
@@ -59,16 +59,23 @@ class MinuiBackendDrm : public MinuiBackend {
GRSurface* Init() override;
GRSurface* Flip() override;
void Blank(bool) override;
+ void Blank(bool blank, DrmConnector index) override;
private:
void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc);
- bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface);
+ bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface,
+ uint32_t* conntcors);
void DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc);
- drmModeConnector* FindMainMonitor(int fd, drmModeRes* resources, uint32_t* mode_index);
+ bool FindAndSetMonitor(int fd, drmModeRes* resources);
+
+ struct DrmInterface {
+ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
+ int current_buffer{ 0 };
+ drmModeCrtc* monitor_crtc{ nullptr };
+ drmModeConnector* monitor_connector{ nullptr };
+ uint32_t selected_mode{ 0 };
+ } drm[DRM_MAX];
- std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
- int current_buffer{ 0 };
- drmModeCrtc* main_monitor_crtc{ nullptr };
- drmModeConnector* main_monitor_connector{ nullptr };
int drm_fd{ -1 };
+ DrmConnector active_display = DRM_MAIN;
};
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 2584017d6..1cb0c0ab8 100644
--- a/minui/graphics_fbdev.cpp
+++ b/minui/graphics_fbdev.cpp
@@ -43,6 +43,10 @@ void MinuiBackendFbdev::Blank(bool blank) {
if (ret < 0) perror("ioctl(): blank");
}
+void MinuiBackendFbdev::Blank(bool blank, DrmConnector index) {
+ fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index);
+}
+
void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) {
if (n > 1 || !double_buffered) return;
@@ -131,8 +135,6 @@ GRSurface* MinuiBackendFbdev::Init() {
SetDisplayedFramebuffer(0);
printf("framebuffer: %d (%zu x %zu)\n", fb_fd.get(), gr_draw->width, gr_draw->height);
-
- Blank(true);
Blank(false);
return gr_draw;
diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h
index 596ba74ea..7e193c4ff 100644
--- a/minui/graphics_fbdev.h
+++ b/minui/graphics_fbdev.h
@@ -56,6 +56,7 @@ class MinuiBackendFbdev : public MinuiBackend {
GRSurface* Init() override;
GRSurface* Flip() override;
void Blank(bool) override;
+ void Blank(bool blank, DrmConnector index) override;
private:
void SetDisplayedFramebuffer(size_t n);
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index 163e41dc6..f9be82f52 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -102,12 +102,22 @@ enum class PixelFormat : int {
RGBX = 2,
BGRA = 3,
ARGB = 4,
+ RGBA = 5, // LSB Alpha
};
-// Initializes the graphics backend and loads font file. Returns 0 on success, or -1 on error. Note
-// that the font initialization failure would be non-fatal, as caller may not need to draw any text
-// at all. Caller can check the font initialization result via gr_sys_font() as needed.
+enum class GraphicsBackend : int {
+ UNKNOWN = 0,
+ DRM = 1,
+ FBDEV = 2,
+};
+
+// Initializes the default graphics backend and loads font file. Returns 0 on success, or -1 on
+// error. Note that the font initialization failure would be non-fatal, as caller may not need to
+// draw any text at all. Caller can check the font initialization result via gr_sys_font() as
+// needed.
int gr_init();
+// Supports backend selection for minui client.
+int gr_init(std::initializer_list<GraphicsBackend> backends);
// Frees the allocated resources. The function is idempotent, and safe to be called if gr_init()
// didn't finish successfully.
@@ -118,6 +128,7 @@ int gr_fb_height();
void gr_flip();
void gr_fb_blank(bool blank);
+void gr_fb_blank(bool blank, int index);
// Clears entire surface to current color.
void gr_clear();
@@ -152,6 +163,7 @@ struct input_event;
using ev_callback = std::function<int(int fd, uint32_t epevents)>;
using ev_set_key_callback = std::function<int(int code, int value)>;
+using ev_set_sw_callback = std::function<int(int code, int value)>;
int ev_init(ev_callback input_cb, bool allow_touch_inputs = false);
void ev_exit();
@@ -159,6 +171,7 @@ int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb);
void ev_iterate_available_keys(const std::function<void(int)>& f);
void ev_iterate_touch_inputs(const std::function<void(int)>& action);
int ev_sync_key_state(const ev_set_key_callback& set_key_cb);
+int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb);
// 'timeout' has the same semantics as poll(2).
// 0 : don't block
diff --git a/minui/resources.cpp b/minui/resources.cpp
index d7b927700..1521c8f17 100644
--- a/minui/resources.cpp
+++ b/minui/resources.cpp
@@ -153,32 +153,57 @@ static void TransformRgbToDraw(const uint8_t* input_row, uint8_t* output_row, in
int width) {
const uint8_t* ip = input_row;
uint8_t* op = output_row;
+ PixelFormat pixel_format = gr_pixel_format();
switch (channels) {
case 1:
// expand gray level to RGBX
for (int x = 0; x < width; ++x) {
- *op++ = *ip;
- *op++ = *ip;
- *op++ = *ip;
- *op++ = 0xff;
+ if (pixel_format == PixelFormat::RGBA) {
+ *op++ = 0xff;
+ *op++ = *ip;
+ *op++ = *ip;
+ *op++ = *ip;
+ } else {
+ *op++ = *ip;
+ *op++ = *ip;
+ *op++ = *ip;
+ *op++ = 0xff;
+ }
ip++;
}
break;
case 3:
- // expand RGBA to RGBX
for (int x = 0; x < width; ++x) {
- *op++ = *ip++;
- *op++ = *ip++;
- *op++ = *ip++;
- *op++ = 0xff;
+ // expand RGBA to RGBX
+ if (pixel_format == PixelFormat::RGBA) {
+ *op++ = 0xff;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ } else {
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = 0xff;
+ }
}
break;
case 4:
- // copy RGBA to RGBX
- memcpy(output_row, input_row, width * 4);
+ if (pixel_format == PixelFormat::RGBA) {
+ for (int x = 0; x < width; ++x) {
+ *op++ = *(ip + 3);
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ ip++;
+ }
+ } else {
+ // copy RGBA to RGBX
+ memcpy(output_row, input_row, width * 4);
+ }
break;
}
}
@@ -201,6 +226,8 @@ int res_create_display_surface(const char* name, GRSurface** pSurface) {
PixelFormat pixel_format = gr_pixel_format();
if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) {
png_set_bgr(png_ptr);
+ } else if (pixel_format == PixelFormat::RGBA) {
+ png_set_swap_alpha(png_ptr);
}
for (png_uint_32 y = 0; y < height; ++y) {
@@ -273,6 +300,8 @@ int res_create_multi_display_surface(const char* name, int* frames, int* fps,
if (gr_pixel_format() == PixelFormat::ARGB || gr_pixel_format() == PixelFormat::BGRA) {
png_set_bgr(png_ptr);
+ } else if (gr_pixel_format() == PixelFormat::RGBA) {
+ png_set_swap_alpha(png_ptr);
}
for (png_uint_32 y = 0; y < height; ++y) {
@@ -316,11 +345,6 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) {
return -8;
}
- PixelFormat pixel_format = gr_pixel_format();
- if (pixel_format == PixelFormat::ARGB || pixel_format == PixelFormat::BGRA) {
- png_set_bgr(png_ptr);
- }
-
for (png_uint_32 y = 0; y < height; ++y) {
uint8_t* p_row = surface->data() + y * surface->row_bytes;
png_read_row(png_ptr, p_row, nullptr);
diff --git a/otautil/Android.bp b/otautil/Android.bp
index 557b8a313..4b043adf1 100644
--- a/otautil/Android.bp
+++ b/otautil/Android.bp
@@ -34,16 +34,21 @@ cc_library_static {
// Minimal set of files to support host build.
srcs: [
+ "asn1_decoder.cpp",
"dirutil.cpp",
+ "package.cpp",
"paths.cpp",
"rangeset.cpp",
"sysutil.cpp",
+ "verifier.cpp",
],
shared_libs: [
"libbase",
+ "libcrypto",
"libcutils",
"libselinux",
+ "libziparchive",
],
export_include_dirs: [
diff --git a/install/asn1_decoder.cpp b/otautil/asn1_decoder.cpp
index 2d81a6e13..2d81a6e13 100644
--- a/install/asn1_decoder.cpp
+++ b/otautil/asn1_decoder.cpp
diff --git a/install/include/install/package.h b/otautil/include/otautil/package.h
index 0b4233238..f4f4d348b 100644
--- a/install/include/install/package.h
+++ b/otautil/include/otautil/package.h
@@ -26,7 +26,7 @@
#include <ziparchive/zip_archive.h>
-#include "verifier.h"
+#include "otautil/verifier.h"
enum class PackageType {
kMemory,
diff --git a/install/include/install/verifier.h b/otautil/include/otautil/verifier.h
index f9e947580..f9e947580 100644
--- a/install/include/install/verifier.h
+++ b/otautil/include/otautil/verifier.h
diff --git a/install/include/private/asn1_decoder.h b/otautil/include/private/asn1_decoder.h
index e5337d9c4..e5337d9c4 100644
--- a/install/include/private/asn1_decoder.h
+++ b/otautil/include/private/asn1_decoder.h
diff --git a/install/package.cpp b/otautil/package.cpp
index 86fc0647d..242204ee6 100644
--- a/install/package.cpp
+++ b/otautil/package.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "install/package.h"
+#include "otautil/package.h"
#include <string.h>
#include <unistd.h>
diff --git a/install/verifier.cpp b/otautil/verifier.cpp
index 3f0260138..8a65566ec 100644
--- a/install/verifier.cpp
+++ b/otautil/verifier.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "install/verifier.h"
+#include "otautil/verifier.h"
#include <errno.h>
#include <stdio.h>
@@ -257,8 +257,8 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
// Check to make sure at least one of the keys matches the signature. Since any key can match,
// we need to try each before determining a verification failure has happened.
- size_t i = 0;
- for (const auto& key : keys) {
+ for (size_t i = 0; i < keys.size(); i++) {
+ const auto& key = keys[i];
const uint8_t* hash;
int hash_nid;
switch (key.hash_len) {
@@ -296,7 +296,6 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
} else {
LOG(INFO) << "Unknown key type " << key.key_type;
}
- i++;
}
if (need_sha1) {
diff --git a/recovery.cpp b/recovery.cpp
index 36924fbdf..4d3901959 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -48,12 +48,12 @@
#include "install/adb_install.h"
#include "install/fuse_install.h"
#include "install/install.h"
-#include "install/package.h"
#include "install/snapshot_utils.h"
#include "install/wipe_data.h"
#include "install/wipe_device.h"
#include "otautil/boot_state.h"
#include "otautil/error_code.h"
+#include "otautil/package.h"
#include "otautil/paths.h"
#include "otautil/sysutil.h"
#include "recovery_ui/screen_ui.h"
@@ -207,8 +207,7 @@ static InstallResult prompt_and_wipe_data(Device* device) {
if (ask_to_wipe_data(device)) {
CHECK(device->GetReason().has_value());
- bool convert_fbe = device->GetReason().value() == "convert_fbe";
- if (WipeData(device, convert_fbe)) {
+ if (WipeData(device)) {
return INSTALL_SUCCESS;
} else {
return INSTALL_ERROR;
@@ -437,10 +436,10 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
save_current_log = true;
if (ui->IsTextVisible()) {
if (ask_to_wipe_data(device)) {
- WipeData(device, false);
+ WipeData(device);
}
} else {
- WipeData(device, false);
+ WipeData(device);
return Device::NO_ACTION;
}
break;
@@ -752,20 +751,20 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
status = INSTALL_ERROR;
} else if (install_with_fuse || should_use_fuse) {
LOG(INFO) << "Installing package " << update_package << " with fuse";
- status = InstallWithFuseFromPath(update_package, ui);
+ status = InstallWithFuseFromPath(update_package, device);
} else if (auto memory_package = Package::CreateMemoryPackage(
update_package,
std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
memory_package != nullptr) {
status = InstallPackage(memory_package.get(), update_package, should_wipe_cache,
- retry_count, ui);
+ retry_count, device);
} else {
// We may fail to memory map the package on 32 bit builds for packages with 2GiB+ size.
// In such cases, we will try to install the package with fuse. This is not the default
// installation method because it introduces a layer of indirection from the kernel space.
LOG(WARNING) << "Failed to memory map package " << update_package
<< "; falling back to install with fuse";
- status = InstallWithFuseFromPath(update_package, ui);
+ status = InstallWithFuseFromPath(update_package, device);
}
if (status != INSTALL_SUCCESS) {
ui->Print("Installation aborted.\n");
@@ -794,8 +793,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
} else if (should_wipe_data) {
save_current_log = true;
CHECK(device->GetReason().has_value());
- bool convert_fbe = device->GetReason().value() == "convert_fbe";
- if (!WipeData(device, convert_fbe)) {
+ if (!WipeData(device)) {
status = INSTALL_ERROR;
}
} else if (should_prompt_and_wipe_data) {
diff --git a/recovery_main.cpp b/recovery_main.cpp
index 80cba61d3..9a358aba7 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -73,12 +73,12 @@ static bool IsDeviceUnlocked() {
return "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", "");
}
-static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity,
- const char* /* tag */, const char* /* file */, unsigned int /* line */,
- const char* message) {
- static constexpr char log_characters[] = "VDIWEF";
+static void UiLogger(android::base::LogId log_buffer_id, android::base::LogSeverity severity,
+ const char* tag, const char* file, unsigned int line, const char* message) {
+ android::base::KernelLogger(log_buffer_id, severity, tag, file, line, message);
+ static constexpr auto&& log_characters = "VDIWEF";
if (severity >= android::base::ERROR && ui != nullptr) {
- ui->Print("E:%s\n", message);
+ ui->Print("ERROR: %10s: %s\n", tag, message);
} else {
fprintf(stdout, "%c:%s\n", log_characters[severity], message);
}
diff --git a/recovery_ui/ethernet_device.cpp b/recovery_ui/ethernet_device.cpp
index d79f41dec..0318db853 100644
--- a/recovery_ui/ethernet_device.cpp
+++ b/recovery_ui/ethernet_device.cpp
@@ -30,10 +30,12 @@
#include "recovery_ui/ethernet_device.h"
#include "recovery_ui/ethernet_ui.h"
-const std::string EthernetDevice::interface = "eth0";
+// Android TV defaults to eth0 for it's interface
+EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) : EthernetDevice(ui, "eth0") {}
-EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui)
- : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) {
+// Allow future users to define the interface as they prefer
+EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui, std::string interface)
+ : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)), interface_(interface) {
if (ctl_sock_ < 0) {
PLOG(ERROR) << "Failed to open socket";
}
@@ -63,7 +65,7 @@ int EthernetDevice::SetInterfaceFlags(const unsigned set, const unsigned clr) {
}
memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
+ strncpy(ifr.ifr_name, interface_.c_str(), IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0;
if (ioctl(ctl_sock_, SIOCGIFFLAGS, &ifr) < 0) {
@@ -96,7 +98,7 @@ void EthernetDevice::SetTitleIPv6LinkLocalAddress(const bool interface_up) {
std::unique_ptr<struct ifaddrs, decltype(&freeifaddrs)> guard{ ifaddr, freeifaddrs };
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_INET6 || interface != ifa->ifa_name) {
+ if (ifa->ifa_addr->sa_family != AF_INET6 || interface_ != ifa->ifa_name) {
continue;
}
diff --git a/recovery_ui/include/recovery_ui/ethernet_device.h b/recovery_ui/include/recovery_ui/ethernet_device.h
index ea710ab93..3aadea200 100644
--- a/recovery_ui/include/recovery_ui/ethernet_device.h
+++ b/recovery_ui/include/recovery_ui/ethernet_device.h
@@ -27,6 +27,7 @@ class EthernetRecoveryUI;
class EthernetDevice : public Device {
public:
explicit EthernetDevice(EthernetRecoveryUI* ui);
+ explicit EthernetDevice(EthernetRecoveryUI* ui, std::string interface);
void PreRecovery() override;
void PreFastboot() override;
@@ -36,7 +37,7 @@ class EthernetDevice : public Device {
void SetTitleIPv6LinkLocalAddress(const bool interface_up);
android::base::unique_fd ctl_sock_;
- static const std::string interface;
+ std::string interface_;
};
#endif // _ETHERNET_RECOVERY_DEVICE_H
diff --git a/recovery_utils/Android.bp b/recovery_utils/Android.bp
index e0e9ec058..9bd66c5d9 100644
--- a/recovery_utils/Android.bp
+++ b/recovery_utils/Android.bp
@@ -31,6 +31,7 @@ cc_defaults {
shared_libs: [
"android.hardware.health@2.0",
"libbase",
+ "libbinder_ndk",
"libext4_utils",
"libfs_mgr",
"libhidlbase",
@@ -42,8 +43,10 @@ cc_defaults {
"libotautil",
// External dependencies.
+ "android.hardware.health-translate-ndk",
"libfstab",
"libhealthhalutils",
+ "libhealthshim",
],
}
@@ -70,6 +73,15 @@ cc_library_static {
"libvold_headers",
],
+ shared_libs: [
+ // The following cannot be placed in librecovery_utils_defaults,
+ // because at the time of writing, android.hardware.health-V1-ndk.so
+ // is not installed to the system image yet. (It is installed
+ // to the recovery ramdisk.) Hence, minadbd_test must link to it
+ // statically.
+ "android.hardware.health-V1-ndk",
+ ],
+
export_include_dirs: [
"include",
],
diff --git a/recovery_utils/battery_utils.cpp b/recovery_utils/battery_utils.cpp
index 323f52537..6b126bdf3 100644
--- a/recovery_utils/battery_utils.cpp
+++ b/recovery_utils/battery_utils.cpp
@@ -20,59 +20,74 @@
#include <unistd.h>
#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <health-shim/shim.h>
#include <healthhalutils/HealthHalUtils.h>
BatteryInfo GetBatteryInfo() {
- using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V2_0::get_health_service;
- using android::hardware::health::V2_0::IHealth;
- using android::hardware::health::V2_0::Result;
- using android::hardware::health::V2_0::toString;
+ using HidlHealth = android::hardware::health::V2_0::IHealth;
+ using aidl::android::hardware::health::BatteryStatus;
+ using aidl::android::hardware::health::HealthShim;
+ using aidl::android::hardware::health::IHealth;
+ using aidl::android::hardware::health::toString;
+ using std::string_literals::operator""s;
- android::sp<IHealth> health = get_health_service();
+ auto service_name = IHealth::descriptor + "/default"s;
+ std::shared_ptr<IHealth> health;
+ if (AServiceManager_isDeclared(service_name.c_str())) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
+ health = IHealth::fromBinder(binder);
+ }
+ if (health == nullptr) {
+ LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
+ android::sp<HidlHealth> hidl_health = get_health_service();
+ if (hidl_health != nullptr) {
+ health = ndk::SharedRefBase::make<HealthShim>(hidl_health);
+ }
+ }
+ if (health == nullptr) {
+ LOG(WARNING) << "No health implementation is found; assuming defaults";
+ }
int wait_second = 0;
while (true) {
auto charge_status = BatteryStatus::UNKNOWN;
-
- if (health == nullptr) {
- LOG(WARNING) << "No health implementation is found; assuming defaults";
- } else {
- health
- ->getChargeStatus([&charge_status](auto res, auto out_status) {
- if (res == Result::SUCCESS) {
- charge_status = out_status;
- }
- })
- .isOk(); // should not have transport error
+ if (health != nullptr) {
+ auto res = health->getChargeStatus(&charge_status);
+ if (!res.isOk()) {
+ LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription();
+ charge_status = BatteryStatus::UNKNOWN;
+ }
}
- // Treat unknown status as on charger. See hardware/interfaces/health/1.0/types.hal for the
- // meaning of the return values.
+ // Treat unknown status as on charger. See hardware/interfaces/health/aidl/BatteryStatus.aidl
+ // for the meaning of the return values.
bool charging = (charge_status != BatteryStatus::DISCHARGING &&
charge_status != BatteryStatus::NOT_CHARGING);
- Result res = Result::UNKNOWN;
int32_t capacity = INT32_MIN;
if (health != nullptr) {
- health
- ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) {
- res = out_res;
- capacity = out_capacity;
- })
- .isOk(); // should not have transport error
+ auto res = health->getCapacity(&capacity);
+ if (!res.isOk()) {
+ LOG(WARNING) << "Unable to call getCapacity: " << res.getDescription();
+ capacity = INT32_MIN;
+ }
}
LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging
- << ", status " << toString(res) << ", capacity " << capacity;
+ << ", capacity " << capacity;
constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
// At startup, the battery drivers in devices like N5X/N6P take some time to load
// the battery profile. Before the load finishes, it reports value 50 as a fake
// capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
// to finish loading the battery profile earlier than 10 seconds after kernel startup.
- if (res == Result::SUCCESS && capacity == 50) {
+ if (capacity == 50) {
if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
+ LOG(INFO) << "Battery capacity == 50, waiting "
+ << (BATTERY_READ_TIMEOUT_IN_SEC - wait_second)
+ << " seconds to ensure this is not a fake value...";
sleep(1);
wait_second++;
continue;
@@ -80,10 +95,12 @@ BatteryInfo GetBatteryInfo() {
}
// If we can't read battery percentage, it may be a device without battery. In this
// situation, use 100 as a fake battery percentage.
- if (res != Result::SUCCESS) {
+ if (capacity == INT32_MIN) {
+ LOG(WARNING) << "Using fake battery capacity 100.";
capacity = 100;
}
+ LOG(INFO) << "GetBatteryInfo() reporting charging " << charging << ", capacity " << capacity;
return BatteryInfo{ charging, capacity };
}
}
diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp
index 19484478c..5c95cba07 100644
--- a/recovery_utils/roots.cpp
+++ b/recovery_utils/roots.cpp
@@ -33,7 +33,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
-#include <cryptfs.h>
+#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
#include <fs_mgr.h>
#include <fs_mgr/roots.h>
@@ -154,53 +154,56 @@ int format_volume(const std::string& volume, const std::string& directory) {
}
bool needs_casefold = false;
- bool needs_projid = false;
if (volume == "/data") {
needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false);
- needs_projid = android::base::GetBoolProperty("external_storage.projid.enabled", false);
- }
-
- // If there's a key_loc that looks like a path, it should be a block device for storing encryption
- // metadata. Wipe it too.
- if (!v->key_loc.empty() && v->key_loc[0] == '/') {
- LOG(INFO) << "Wiping " << v->key_loc;
- int fd = open(v->key_loc.c_str(), O_WRONLY | O_CREAT, 0644);
- if (fd == -1) {
- PLOG(ERROR) << "format_volume: Failed to open " << v->key_loc;
- return -1;
- }
- wipe_block_device(fd, get_file_size(fd));
- close(fd);
}
int64_t length = 0;
if (v->length > 0) {
length = v->length;
- } else if (v->length < 0 || v->key_loc == "footer") {
+ } else if (v->length < 0) {
android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDONLY));
if (fd == -1) {
PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
return -1;
}
- length = get_file_size(fd.get(), v->length ? -v->length : CRYPT_FOOTER_OFFSET);
+ length = get_file_size(fd.get(), -v->length);
if (length <= 0) {
LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device;
return -1;
}
}
+ // If the raw disk will be used as a metadata encrypted device mapper target,
+ // next boot will do encrypt_in_place the raw disk which gives a subtle duration
+ // to get any failure in the process. In order to avoid it, let's simply wipe
+ // the raw disk if we don't reserve any space, which behaves exactly same as booting
+ // after "fastboot -w".
+ if (!v->metadata_key_dir.empty() && length == 0) {
+ android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR));
+ if (fd == -1) {
+ PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
+ return -1;
+ }
+ int64_t device_size = get_file_size(fd.get(), 0);
+ if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) {
+ LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size "
+ << device_size;
+ return 0;
+ }
+ }
+
if (v->fs_type == "ext4") {
static constexpr int kBlockSize = 4096;
std::vector<std::string> mke2fs_args = {
"/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize),
};
- // Project ID's require wider inodes. The Quotas themselves are enabled by tune2fs on boot.
- if (needs_projid) {
- mke2fs_args.push_back("-I");
- mke2fs_args.push_back("512");
- }
+ // Following is added for Project ID's quota as they require wider inodes.
+ // The Quotas themselves are enabled by tune2fs on boot.
+ mke2fs_args.push_back("-I");
+ mke2fs_args.push_back("512");
if (v->fs_mgr_flags.ext_meta_csum) {
mke2fs_args.push_back("-O");
@@ -249,10 +252,10 @@ int format_volume(const std::string& volume, const std::string& directory) {
"-g",
"android",
};
- if (needs_projid) {
- make_f2fs_cmd.push_back("-O");
- make_f2fs_cmd.push_back("project_quota,extra_attr");
- }
+
+ make_f2fs_cmd.push_back("-O");
+ make_f2fs_cmd.push_back("project_quota,extra_attr");
+
if (needs_casefold) {
make_f2fs_cmd.push_back("-O");
make_f2fs_cmd.push_back("casefold");
diff --git a/tests/Android.bp b/tests/Android.bp
index 5ef4d58c0..9ad3d3b80 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -134,11 +134,22 @@ cc_test {
test_suites: ["device-tests"],
+ tidy_timeout_srcs: [
+ "unit/commands_test.cpp",
+ ],
+
srcs: [
"unit/*.cpp",
],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+
static_libs: libapplypatch_static_libs + librecovery_static_libs + [
+ "android.hardware.health-translate-ndk",
+ "android.hardware.health-V1-ndk",
+ "libhealthshim",
"librecovery_ui",
"libfusesideload",
"libminui",
@@ -185,6 +196,10 @@ cc_test_host {
"libupdater_defaults",
],
+ tidy_timeout_srcs: [
+ "unit/host/imgdiff_test.cpp",
+ ],
+
srcs: [
"unit/host/*",
],
diff --git a/tests/fuzz/verify_package_fuzzer.cpp b/tests/fuzz/verify_package_fuzzer.cpp
index baa44e070..36c853465 100644
--- a/tests/fuzz/verify_package_fuzzer.cpp
+++ b/tests/fuzz/verify_package_fuzzer.cpp
@@ -17,7 +17,7 @@
#include "fuzzer/FuzzedDataProvider.h"
#include "install/install.h"
-#include "install/package.h"
+#include "otautil/package.h"
#include "recovery_ui/stub_ui.h"
std::unique_ptr<Package> CreatePackage(std::vector<uint8_t>& content) {
diff --git a/tests/unit/host/update_simulator_test.cpp b/tests/unit/host/update_simulator_test.cpp
index fb1217877..1603982e4 100644
--- a/tests/unit/host/update_simulator_test.cpp
+++ b/tests/unit/host/update_simulator_test.cpp
@@ -101,7 +101,7 @@ static void RunSimulation(std::string_view src_tf, std::string_view ota_package,
// TODO(xunchang) check the recovery&system has the expected contents.
}
-class UpdateSimulatorTest : public ::testing::Test {
+class DISABLED_UpdateSimulatorTest : public ::testing::Test {
protected:
void SetUp() override {
std::vector<string> props = {
@@ -147,7 +147,7 @@ class UpdateSimulatorTest : public ::testing::Test {
string sparse_system_string_;
};
-TEST_F(UpdateSimulatorTest, TargetFile_ExtractImage) {
+TEST_F(DISABLED_UpdateSimulatorTest, TargetFile_ExtractImage) {
TemporaryFile zip_file;
AddZipEntries(zip_file.release(), { { "META/misc_info.txt", "extfs_sparse_flag=-s" },
{ "IMAGES/system.img", sparse_system_string_ } });
@@ -166,7 +166,7 @@ TEST_F(UpdateSimulatorTest, TargetFile_ExtractImage) {
ASSERT_EQ(expected_content, content);
}
-TEST_F(UpdateSimulatorTest, TargetFile_ParseFstabInfo) {
+TEST_F(DISABLED_UpdateSimulatorTest, TargetFile_ParseFstabInfo) {
TemporaryFile zip_file;
AddZipEntries(zip_file.release(),
{ { "META/misc_info.txt", "" },
@@ -195,7 +195,7 @@ TEST_F(UpdateSimulatorTest, TargetFile_ParseFstabInfo) {
EXPECT_EQ(expected, transformed);
}
-TEST_F(UpdateSimulatorTest, BuildInfo_ParseTargetFile) {
+TEST_F(DISABLED_UpdateSimulatorTest, BuildInfo_ParseTargetFile) {
std::map<string, string> entries = {
{ "META/misc_info.txt", "" },
{ "SYSTEM/build.prop", build_prop_string_ },
@@ -240,7 +240,7 @@ TEST_F(UpdateSimulatorTest, BuildInfo_ParseTargetFile) {
}
}
-TEST_F(UpdateSimulatorTest, RunUpdateSmoke) {
+TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateSmoke) {
string recovery_img_string = "recovery.img";
string boot_img_string = "boot.img";
@@ -326,7 +326,7 @@ TEST_F(UpdateSimulatorTest, RunUpdateSmoke) {
RunSimulation(src_tf.path, ota_package.path, true);
}
-TEST_F(UpdateSimulatorTest, RunUpdateUnrecognizedFunction) {
+TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateUnrecognizedFunction) {
std::map<string, string> src_entries{
{ "META/misc_info.txt", "extfs_sparse_flag=-s" },
{ "IMAGES/system.img", sparse_system_string_ },
@@ -350,7 +350,7 @@ TEST_F(UpdateSimulatorTest, RunUpdateUnrecognizedFunction) {
RunSimulation(src_tf.path, ota_package.path, false);
}
-TEST_F(UpdateSimulatorTest, RunUpdateApplyPatchFailed) {
+TEST_F(DISABLED_UpdateSimulatorTest, RunUpdateApplyPatchFailed) {
string recovery_img_string = "recovery.img";
string boot_img_string = "boot.img";
diff --git a/tests/unit/package_test.cpp b/tests/unit/package_test.cpp
index 164a93d57..66882bb40 100644
--- a/tests/unit/package_test.cpp
+++ b/tests/unit/package_test.cpp
@@ -26,7 +26,7 @@
#include <ziparchive/zip_writer.h>
#include "common/test_constants.h"
-#include "install/package.h"
+#include "otautil/package.h"
class PackageTest : public ::testing::Test {
protected:
diff --git a/tests/unit/verifier_test.cpp b/tests/unit/verifier_test.cpp
index ded23c52f..08a3ddfc4 100644
--- a/tests/unit/verifier_test.cpp
+++ b/tests/unit/verifier_test.cpp
@@ -35,8 +35,8 @@
#include <ziparchive/zip_writer.h>
#include "common/test_constants.h"
-#include "install/package.h"
-#include "install/verifier.h"
+#include "otautil/package.h"
+#include "otautil/verifier.h"
#include "otautil/sysutil.h"
using namespace std::string_literals;
diff --git a/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: