summaryrefslogtreecommitdiff
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.cpp94
-rw-r--r--minui/graphics.h11
-rw-r--r--minui/graphics_drm.cpp274
-rw-r--r--minui/graphics_drm.h140
-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--tools/recovery_l10n/res/values-ky/strings.xml2
-rw-r--r--tools/recovery_l10n/res/values-nb/strings.xml2
-rw-r--r--tools/recovery_l10n/res/values-te/strings.xml2
-rw-r--r--update_verifier/Android.bp19
-rw-r--r--update_verifier/care_map_generator.py4
56 files changed, 647 insertions, 467 deletions
diff --git a/Android.bp b/Android.bp
index 52de7703..bd957050 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 96af417b..8506040f 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 a1ce3c66..68bf6f8b 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 79dd9f77..45c72e38 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 28aa06f4..023d48b9 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 b70d54e5..1ea56cd4 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 e4cf09b2..d58158dd 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 37bcdd03..5e1e847a 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 5cacb8bd..e4afecff 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 8fa1b5c2..2183d084 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 3d948030..07cbe96f 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 3a6581f6..b76fc78e 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -106,12 +106,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 ee79a32c..b12e5294 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 91d5d1bd..c4a350d1 100644
--- a/install/fuse_install.cpp
+++ b/install/fuse_install.cpp
@@ -153,10 +153,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);
@@ -190,8 +191,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;
}
@@ -302,7 +303,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 63b116ae..29c283f4 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 bef23e9c..0f5102f8 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 b34891f3..42cad871 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 c60b9999..903ddfdc 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 b9b3913e..27570059 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 4eecf72c..024c1e1d 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 915c87b4..0a525fa9 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 2bcfece4..9d3f7334 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 f68f6c81..02fb3638 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 863ac747..b307a497 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 dce1e619..b24c2b11 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 3c45a406..5408c93e 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 4b40839c..e9ee9347 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -56,7 +56,6 @@
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
-#include <android-base/properties.h>
#include <string>
#include <drm_fourcc.h>
#include <xf86drm.h>
@@ -65,13 +64,13 @@
#include "minui/minui.h"
-#define find_prop_id(_res, type, Type, obj_id, prop_name, prop_id) \
+#define find_prop_id(_res, type, Type, obj_id, prop_name, prop_id, index) \
do { \
int j = 0; \
int prop_count = 0; \
struct Type *obj = NULL; \
obj = (_res); \
- if (!obj || main_monitor_##type->type##_id != (obj_id)){ \
+ if (!obj || drm[index].monitor_##type->type##_id != (obj_id)){ \
prop_id = 0; \
break; \
} \
@@ -83,8 +82,8 @@
0 : obj->props_info[j]->prop_id; \
} while (0)
-#define add_prop(res, type, Type, id, id_name, id_val) \
- find_prop_id(res, type, Type, id, id_name, prop_id); \
+#define add_prop(res, type, Type, id, id_name, id_val, index) \
+ find_prop_id(res, type, Type, id, id_name, prop_id, index); \
if (prop_id) \
drmModeAtomicAddProperty(atomic_req, id, prop_id, id_val);
@@ -190,50 +189,11 @@ static int atomic_add_prop_to_plane(Plane *plane_res, drmModeAtomicReq *req,
return 0;
}
-static int SetupSprBlob(int fd, uint32_t* blob_id) {
- SPRPackType pack_type = SPRPackType::kPentile;
- SPRFilterType filter_type = SPRFilterType::kFourTap;
- SPRAdaptiveModeType adpative_mode = SPRAdaptiveModeType::kYYGM;
-
- drm_msm_spr_init_cfg spr_init_cfg;
- spr_init_cfg.cfg0 = 1;
- spr_init_cfg.cfg1 = 1;
- spr_init_cfg.cfg2 = 1;
- spr_init_cfg.cfg3 = 0;
- spr_init_cfg.flags = 0;
- spr_init_cfg.cfg4 = (pack_type == SPRPackType::kRGBW);
- spr_init_cfg.cfg5 = DefaultColorPhaseIncrement.at(pack_type);
- spr_init_cfg.cfg6 = DefaultColorPhaseRepeat.at(pack_type);
- spr_init_cfg.cfg7 = static_cast<uint16_t>(filter_type);
- spr_init_cfg.cfg8 = static_cast<uint16_t>(adpative_mode);
- if (pack_type == SPRPackType::kRGBW) {
- spr_init_cfg.cfg9 = 512;
- std::copy(DefaultRGBWGains.begin(), DefaultRGBWGains.end(), spr_init_cfg.cfg11);
- }
- spr_init_cfg.cfg10 = 0;
- std::copy(DecimationRatioMap.at(pack_type).begin(), DecimationRatioMap.at(pack_type).end(),
- spr_init_cfg.cfg11);
- std::copy(DefaultOPRGains.begin(), DefaultOPRGains.end(), spr_init_cfg.cfg13);
- std::copy(DefaultAdaptiveStrengths.begin(), DefaultAdaptiveStrengths.end(), spr_init_cfg.cfg14);
- std::copy(DefaultOPROffsets.begin(), DefaultOPROffsets.end(), spr_init_cfg.cfg15);
- std::copy(DefaultFilterCoeffsMap.at(filter_type).begin(),
- DefaultFilterCoeffsMap.at(filter_type).end(), spr_init_cfg.cfg16);
- std::copy(DefaultColorPhaseMap.at(pack_type).begin(), DefaultColorPhaseMap.at(pack_type).end(),
- spr_init_cfg.cfg17);
-
- if (drmModeCreatePropertyBlob(fd, &spr_init_cfg, sizeof(drm_msm_spr_init_cfg), blob_id)) {
- printf("failed to create spr blob\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-int MinuiBackendDrm::AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req) {
+int MinuiBackendDrm::AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req, DrmConnector index) {
uint32_t src_x, src_y, src_w, src_h;
uint32_t crtc_x, crtc_y, crtc_w, crtc_h;
- int width = main_monitor_crtc->mode.hdisplay;
- int height = main_monitor_crtc->mode.vdisplay;
+ int width = drm[index].monitor_crtc->mode.hdisplay;
+ int height = drm[index].monitor_crtc->mode.vdisplay;
int zpos = 0;
src_y = 0;
@@ -254,7 +214,7 @@ int MinuiBackendDrm::AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_r
if (atomic_add_prop_to_plane(plane_res, atomic_req,
plane_res[plane].plane->plane_id, "FB_ID",
- GRSurfaceDrms[current_buffer]->fb_id))
+ drm[index].GRSurfaceDrms[drm[index].current_buffer]->fb_id))
return -EINVAL;
if (atomic_add_prop_to_plane(plane_res, atomic_req,
@@ -291,23 +251,20 @@ int MinuiBackendDrm::AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_r
if (atomic_add_prop_to_plane(plane_res, atomic_req,
plane_res[plane].plane->plane_id, "CRTC_ID",
- main_monitor_crtc->crtc_id))
+ drm[index].monitor_crtc->crtc_id))
return -EINVAL;
return 0;
}
-int MinuiBackendDrm::TeardownPipeline(drmModeAtomicReqPtr atomic_req) {
+int MinuiBackendDrm::TeardownPipeline(drmModeAtomicReqPtr atomic_req, DrmConnector index) {
uint32_t i, prop_id;
int ret;
/* During suspend, tear down pipeline */
- add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id, "CRTC_ID", 0);
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "MODE_ID", 0);
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "ACTIVE", 0);
- if (spr_enabled) {
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "SDE_SPR_INIT_CFG_V1", 0);
- }
+ add_prop(&conn_res, connector, Connector, drm[index].monitor_connector->connector_id, "CRTC_ID", 0, index);
+ add_prop(&crtc_res, crtc, Crtc, drm[index].monitor_crtc->crtc_id, "MODE_ID", 0, index);
+ add_prop(&crtc_res, crtc, Crtc, drm[index].monitor_crtc->crtc_id, "ACTIVE", 0, index);
for(i = 0; i < number_of_lms; i++) {
ret = atomic_add_prop_to_plane(plane_res, atomic_req,
@@ -326,24 +283,20 @@ int MinuiBackendDrm::TeardownPipeline(drmModeAtomicReqPtr atomic_req) {
return 0;
}
-int MinuiBackendDrm::SetupPipeline(drmModeAtomicReqPtr atomic_req) {
+int MinuiBackendDrm::SetupPipeline(drmModeAtomicReqPtr atomic_req, DrmConnector index) {
uint32_t i, prop_id;
int ret;
for(i = 0; i < number_of_lms; i++) {
- add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id,
- "CRTC_ID", main_monitor_crtc->crtc_id);
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "MODE_ID", crtc_res.mode_blob_id);
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "ACTIVE", 1);
- if (spr_enabled) {
- add_prop(&crtc_res, crtc, Crtc, main_monitor_crtc->crtc_id, "SDE_SPR_INIT_CFG_V1",
- crtc_res.spr_blob_id);
- }
+ add_prop(&conn_res, connector, Connector, drm[index].monitor_connector->connector_id,
+ "CRTC_ID", drm[index].monitor_crtc->crtc_id, index);
+ add_prop(&crtc_res, crtc, Crtc, drm[index].monitor_crtc->crtc_id, "MODE_ID", crtc_res.mode_blob_id, index);
+ add_prop(&crtc_res, crtc, Crtc, drm[index].monitor_crtc->crtc_id, "ACTIVE", 1, index);
}
/* Setup planes */
for(i = 0; i < number_of_lms; i++) {
- ret = AtomicPopulatePlane(i, atomic_req);
+ ret = AtomicPopulatePlane(i, atomic_req, index);
if (ret < 0) {
printf("Error populating plane_id = %d\n", plane_res[i].plane->plane_id);
return ret;
@@ -423,6 +376,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(
@@ -446,25 +401,49 @@ 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;
}
-int MinuiBackendDrm::DrmDisableCrtc(drmModeAtomicReqPtr atomic_req) {
- return TeardownPipeline(atomic_req);
+int MinuiBackendDrm::DrmDisableCrtc(drmModeAtomicReqPtr atomic_req, DrmConnector index) {
+ return TeardownPipeline(atomic_req, index);
}
-int MinuiBackendDrm::DrmEnableCrtc(drmModeAtomicReqPtr atomic_req){
- return SetupPipeline(atomic_req);
+int MinuiBackendDrm::DrmEnableCrtc(drmModeAtomicReqPtr atomic_req, DrmConnector index){
+ return SetupPipeline(atomic_req, index);
}
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;
+ }
+
int ret = 0;
if (blank == current_blank_state)
@@ -477,9 +456,9 @@ void MinuiBackendDrm::Blank(bool blank) {
}
if (blank)
- ret = DrmDisableCrtc(atomic_req);
+ ret = DrmDisableCrtc(atomic_req, index);
else
- ret = DrmEnableCrtc(atomic_req);
+ ret = DrmEnableCrtc(atomic_req, index);
if (!ret)
ret = drmModeAtomicCommit(drm_fd, atomic_req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
@@ -530,18 +509,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) {
@@ -559,8 +541,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,
@@ -568,30 +549,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;
+ for (int drm_index = 0; drm_index < drmConnectors.size(); drm_index++) {
+ drm[drm_index].monitor_connector = drmConnectors[drm_index];
- *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;
+ 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) {
@@ -604,11 +596,11 @@ void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmMode
if (crtc->crtc_id != main_crtc->crtc_id) {
// Switching to atomic commit. Given only crtc, we can only set ACTIVE = 0
// to disable any Nonmain CRTCs
- find_prop_id(&crtc_res, crtc, Crtc, crtc->crtc_id, "ACTIVE", prop_id);
+ find_prop_id(&crtc_res, crtc, Crtc, crtc->crtc_id, "ACTIVE", prop_id, i);
if (prop_id == 0)
return;
- if (drmModeAtomicAddProperty(atomic_req, main_monitor_crtc->crtc_id, prop_id, 0) < 0)
+ if (drmModeAtomicAddProperty(atomic_req, drm[i].monitor_crtc->crtc_id, prop_id, 0) < 0)
return;
}
drmModeFreeCrtc(crtc);
@@ -620,7 +612,7 @@ void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmMode
drmModeAtomicFree(atomic_req);
}
-void MinuiBackendDrm::UpdatePlaneFB() {
+void MinuiBackendDrm::UpdatePlaneFB(DrmConnector index) {
uint32_t i, prop_id;
/* Set atomic req */
@@ -633,13 +625,13 @@ void MinuiBackendDrm::UpdatePlaneFB() {
/* Add conn-crtc association property required
* for driver to recognize quadpipe topology.
*/
- add_prop(&conn_res, connector, Connector, main_monitor_connector->connector_id,
- "CRTC_ID", main_monitor_crtc->crtc_id);
+ add_prop(&conn_res, connector, Connector, drm[index].monitor_connector->connector_id,
+ "CRTC_ID", drm[index].monitor_crtc->crtc_id, index);
/* Add property */
for(i = 0; i < number_of_lms; i++)
drmModeAtomicAddProperty(atomic_req, plane_res[i].plane->plane_id,
- fb_prop_id, GRSurfaceDrms[current_buffer]->fb_id);
+ fb_prop_id, drm[index].GRSurfaceDrms[drm[index].current_buffer]->fb_id);
/* Commit changes */
int32_t ret;
@@ -656,7 +648,6 @@ GRSurface* MinuiBackendDrm::Init() {
drmModeRes* res = nullptr;
drm_fd = -1;
- spr_enabled = android::base::GetIntProperty("vendor.display.enable_spr", 0);
number_of_lms = DEFAULT_NUM_LMS;
/* Consider DRM devices in order. */
for (int i = 0; i < DRM_MAX_MINOR; i++) {
@@ -691,39 +682,41 @@ 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");
+ if (!FindAndSetMonitor(drm_fd, res)) {
+ fprintf(stderr, "Failed to find main monitor_connector\n");
drmModeFreeResources(res);
- close(drm_fd);
return nullptr;
}
- main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
- if (!main_monitor_crtc) {
- fprintf(stderr, "Failed to find main_monitor_crtc\n");
- drmModeFreeResources(res);
- close(drm_fd);
- return nullptr;
- }
-
- 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);
drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
@@ -735,7 +728,7 @@ GRSurface* MinuiBackendDrm::Init() {
/* Set crtc resources */
crtc_res.props = drmModeObjectGetProperties(drm_fd,
- main_monitor_crtc->crtc_id,
+ drm[DRM_MAIN].monitor_crtc->crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!crtc_res.props)
return NULL;
@@ -752,7 +745,7 @@ GRSurface* MinuiBackendDrm::Init() {
/* Set connector resources */
conn_res.props = drmModeObjectGetProperties(drm_fd,
- main_monitor_connector->connector_id,
+ drm[DRM_MAIN].monitor_connector->connector_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!conn_res.props)
return NULL;
@@ -803,15 +796,8 @@ GRSurface* MinuiBackendDrm::Init() {
drmModeFreePlaneResources(plane_options);
plane_options = NULL;
- /* Setup spr blob if enabled */
- if (spr_enabled) {
- if (SetupSprBlob(drm_fd, &crtc_res.spr_blob_id)) {
- return NULL;
- }
- }
-
/* Setup pipe and blob_id */
- if (drmModeCreatePropertyBlob(drm_fd, &main_monitor_crtc->mode, sizeof(drmModeModeInfo),
+ if (drmModeCreatePropertyBlob(drm_fd, &drm[DRM_MAIN].monitor_crtc->mode, sizeof(drmModeModeInfo),
&crtc_res.mode_blob_id)) {
printf("failed to create mode blob\n");
return NULL;
@@ -824,21 +810,25 @@ GRSurface* MinuiBackendDrm::Init() {
Blank(false);
- return GRSurfaceDrms[0].get();
+ return drm[DRM_MAIN].GRSurfaceDrms[0].get();
}
GRSurface* MinuiBackendDrm::Flip() {
- UpdatePlaneFB();
+ UpdatePlaneFB(active_display);
- current_buffer = 1 - current_buffer;
- return GRSurfaceDrms[current_buffer].get();
+ drm[active_display].current_buffer = 1 - drm[active_display].current_buffer;
+ return drm[active_display].GRSurfaceDrms[drm[active_display].current_buffer].get();
}
MinuiBackendDrm::~MinuiBackendDrm() {
+ for (int i = 0; i < DRM_MAX; i++) {
+ if (drm[i].monitor_connector) {
+ drmModeFreeCrtc(drm[i].monitor_crtc);
+ drmModeFreeConnector(drm[i].monitor_connector);
+ }
+ }
Blank(true);
drmModeDestroyPropertyBlob(drm_fd, crtc_res.mode_blob_id);
- drmModeFreeCrtc(main_monitor_crtc);
- drmModeFreeConnector(main_monitor_connector);
close(drm_fd);
drm_fd = -1;
}
diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h
index 676410e4..2d6fab3a 100644
--- a/minui/graphics_drm.h
+++ b/minui/graphics_drm.h
@@ -20,8 +20,6 @@
#include <stdint.h>
#include <memory>
-#include <map>
-#include <array>
#include <xf86drmMode.h>
@@ -32,93 +30,10 @@
#define NUM_PLANES 4
#define DEFAULT_NUM_LMS 2
-#define SPR_INIT_PARAM_SIZE_1 4
-#define SPR_INIT_PARAM_SIZE_2 5
-#define SPR_INIT_PARAM_SIZE_3 16
-#define SPR_INIT_PARAM_SIZE_4 24
-#define SPR_INIT_PARAM_SIZE_5 32
-
-enum class SPRPackType {
- kPentile,
- kRGBW,
- kYYGW,
- kYYGM,
- kDelta3,
- kMax = 0xFF,
-};
-
-enum class SPRFilterType {
- kPixelDrop,
- kBilinear,
- kFourTap,
- kAdaptive,
- kMax = 0xFF,
-};
-
-enum class SPRAdaptiveModeType {
- kYYGM,
- kYYGW,
- kMax = 0xFF,
-};
-
-static const std::map<SPRPackType, uint32_t> DefaultColorPhaseIncrement = {
- { { { SPRPackType::kPentile }, { 8 } },
- { { SPRPackType::kYYGM }, { 6 } },
- { { SPRPackType::kYYGW }, { 6 } },
- { { SPRPackType::kDelta3 }, { 6 } },
- { { SPRPackType::kRGBW }, { 8 } } }
-};
-static const std::map<SPRPackType, uint32_t> DefaultColorPhaseRepeat = {
- { { { SPRPackType::kPentile }, { 2 } },
- { { SPRPackType::kYYGM }, { 2 } },
- { { SPRPackType::kYYGW }, { 2 } },
- { { SPRPackType::kDelta3 }, { 2 } },
- { { SPRPackType::kRGBW }, { 2 } } }
-};
-static const std::map<SPRPackType, std::array<uint16_t, SPR_INIT_PARAM_SIZE_1>> DecimationRatioMap{
- {
- { { SPRPackType::kPentile }, { 1, 0, 1, 0 } },
- { { SPRPackType::kYYGM }, { 2, 2, 2, 0 } },
- { { SPRPackType::kYYGW }, { 2, 2, 2, 0 } },
- { { SPRPackType::kRGBW }, { 1, 1, 1, 1 } },
- }
-};
-static const std::map<SPRFilterType, std::array<int16_t, SPR_INIT_PARAM_SIZE_3>>
- DefaultFilterCoeffsMap{
- { { { SPRFilterType::kPixelDrop }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { SPRFilterType::kBilinear },
- { 0, 512, 0, 0, -33, 443, 110, -8, -23, 279, 279, -23, -8, 110, 443, -33 } },
- { { SPRFilterType::kFourTap },
- { 128, 256, 128, 0, 86, 241, 164, 21, 52, 204, 204, 52, 21, 164, 241, 86 } },
- { { SPRFilterType::kAdaptive },
- { 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0, 0, 256, 256, 0 } } }
- };
-static const std::map<SPRPackType, std::array<int16_t, SPR_INIT_PARAM_SIZE_4>>
- DefaultColorPhaseMap{
- { { { SPRPackType::kPentile },
- { -2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { SPRPackType::kYYGM },
- { -3, 0, 0, 0, 0, 0, -1, 2, 1, 1, 0, 0, 1, -2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { SPRPackType::kYYGW },
- { -4, 2, 0, 0, 0, -1, 2, 2, 0, -1, -1, -1, 2, 2, -1, -1, -1, 2, 0, 0, 0, 0, 0, 0 } },
- { { SPRPackType::kDelta3 },
- { -3, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { SPRPackType::kRGBW },
- { -4, 0, 0, 0, 0, 0, -2, 2, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0 } } }
- };
-static const std::array<uint16_t, SPR_INIT_PARAM_SIZE_1> DefaultRGBWGains = { 1024, 1024, 1024, 341 };
-static const std::array<uint16_t, SPR_INIT_PARAM_SIZE_1> DefaultOPRGains = { 341, 341, 341, 0 };
-static const std::array<uint16_t, SPR_INIT_PARAM_SIZE_2> DefaultAdaptiveStrengths = { 0, 4, 8, 12, 16 };
-static const std::array<uint16_t, SPR_INIT_PARAM_SIZE_5> DefaultOPROffsets = {
- 0, 132, 264, 396, 529, 661, 793, 925, 1057, 1189, 1321, 1453, 1586, 1718, 1850, 1982,
- 2114, 2246, 2378, 2510, 2643, 2775, 2907, 3039, 3171, 3303, 3435, 3567, 3700, 3832, 3964, 4095
-};
-
struct Crtc {
drmModeObjectProperties *props;
drmModePropertyRes **props_info;
uint32_t mode_blob_id;
- uint32_t spr_blob_id;
};
struct Connector {
@@ -132,28 +47,6 @@ struct Plane {
drmModePropertyRes ** props_info;
};
-struct drm_msm_spr_init_cfg {
- __u64 flags;
- __u16 cfg0;
- __u16 cfg1;
- __u16 cfg2;
- __u16 cfg3;
- __u16 cfg4;
- __u16 cfg5;
- __u16 cfg6;
- __u16 cfg7;
- __u16 cfg8;
- __u16 cfg9;
- __u32 cfg10;
- __u16 cfg11[SPR_INIT_PARAM_SIZE_1];
- __u16 cfg12[SPR_INIT_PARAM_SIZE_1];
- __u16 cfg13[SPR_INIT_PARAM_SIZE_1];
- __u16 cfg14[SPR_INIT_PARAM_SIZE_2];
- __u16 cfg15[SPR_INIT_PARAM_SIZE_5];
- int cfg16[SPR_INIT_PARAM_SIZE_3];
- int cfg17[SPR_INIT_PARAM_SIZE_4];
-};
-
class GRSurfaceDrm : public GRSurface {
public:
~GRSurfaceDrm() override;
@@ -187,27 +80,34 @@ class MinuiBackendDrm : public MinuiBackend {
GRSurface* Init() override;
GRSurface* Flip() override;
void Blank(bool) override;
+ void Blank(bool blank, DrmConnector index) override;
private:
- int DrmDisableCrtc(drmModeAtomicReqPtr atomic_req);
- int DrmEnableCrtc(drmModeAtomicReqPtr atomic_req);
+ int DrmDisableCrtc(drmModeAtomicReqPtr atomic_req, DrmConnector index);
+ int DrmEnableCrtc(drmModeAtomicReqPtr atomic_req, DrmConnector index);
+ 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);
- int SetupPipeline(drmModeAtomicReqPtr atomic_req);
- int TeardownPipeline(drmModeAtomicReqPtr atomic_req);
- void UpdatePlaneFB();
- int AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req);
-
- std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
- int current_buffer{ 0 };
- drmModeCrtc* main_monitor_crtc{ nullptr };
- drmModeConnector* main_monitor_connector{ nullptr };
+ int SetupPipeline(drmModeAtomicReqPtr atomic_req, DrmConnector index);
+ int TeardownPipeline(drmModeAtomicReqPtr atomic_req, DrmConnector index);
+ void UpdatePlaneFB(DrmConnector index);
+ int AtomicPopulatePlane(int plane, drmModeAtomicReqPtr atomic_req, DrmConnector 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];
+
int drm_fd{ -1 };
+ DrmConnector active_display = DRM_MAIN;
bool current_blank_state = true;
int fb_prop_id;
struct Crtc crtc_res;
struct Connector conn_res;
struct Plane plane_res[NUM_PLANES];
uint32_t number_of_lms;
- uint32_t spr_enabled;
};
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 2584017d..1cb0c0ab 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 596ba74e..7e193c4f 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 163e41dc..f9be82f5 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 d7b92770..1521c8f1 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 557b8a31..4b043adf 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 2d81a6e1..2d81a6e1 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 0b423323..f4f4d348 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 f9e94758..f9e94758 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 e5337d9c..e5337d9c 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 86fc0647..242204ee 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 3f026013..8a65566e 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 134a80d7..ffaa4dec 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -51,13 +51,13 @@
#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/dirutil.h"
#include "otautil/error_code.h"
+#include "otautil/package.h"
#include "otautil/paths.h"
#include "otautil/sysutil.h"
#include "recovery_ui/screen_ui.h"
@@ -216,8 +216,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;
@@ -515,10 +514,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;
@@ -848,20 +847,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");
@@ -890,8 +889,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 80cba61d..9a358aba 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 d79f41de..0318db85 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 ea710ab9..3aadea20 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 e0e9ec05..9bd66c5d 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 323f5253..6b126bdf 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 52eae384..62ccdb6a 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 5ef4d58c..9ad3d3b8 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 baa44e07..36c85346 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 fb121787..1603982e 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 164a93d5..66882bb4 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 ded23c52..08a3ddfc 100644
--- a/tests/unit/verifier_test.cpp
+++ b/tests/unit/verifier_test.cpp
@@ -35,8 +35,8 @@
#include <ziparchive/zip_writer.h>
#include "common/test_constants.h"
-#include "install/package.h"
-#include "install/verifier.h"
+#include "otautil/package.h"
+#include "otautil/verifier.h"
#include "otautil/sysutil.h"
using namespace std::string_literals;
diff --git a/tools/recovery_l10n/res/values-ky/strings.xml b/tools/recovery_l10n/res/values-ky/strings.xml
index 45fcd15e..67dca2a3 100644
--- a/tools/recovery_l10n/res/values-ky/strings.xml
+++ b/tools/recovery_l10n/res/values-ky/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recovery_installing" msgid="2013591905463558223">"Тутум жаңырууда"</string>
+ <string name="recovery_installing" msgid="2013591905463558223">"Система жаңырууда"</string>
<string name="recovery_erasing" msgid="7334826894904037088">"Тазаланууда"</string>
<string name="recovery_no_command" msgid="4465476568623024327">"Буйрук берилген жок"</string>
<string name="recovery_error" msgid="5748178989622716736">"Ката!"</string>
diff --git a/tools/recovery_l10n/res/values-nb/strings.xml b/tools/recovery_l10n/res/values-nb/strings.xml
index e8cad136..61d1173c 100644
--- a/tools/recovery_l10n/res/values-nb/strings.xml
+++ b/tools/recovery_l10n/res/values-nb/strings.xml
@@ -7,7 +7,7 @@
<string name="recovery_error" msgid="5748178989622716736">"Feil!"</string>
<string name="recovery_installing_security" msgid="9184031299717114342">"Installerer sikkerhetsoppdateringen"</string>
<string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Kan ikke laste inn Android-systemet. Dataene dine er muligens skadet. Hvis du fortsetter å se denne meldingen, må du muligens tilbakestille til fabrikkstandard og tømme alle brukerdataene som er lagret på denne enheten."</string>
- <string name="recovery_try_again" msgid="7168248750158873496">"Prøv igjen"</string>
+ <string name="recovery_try_again" msgid="7168248750158873496">"Prøv på nytt"</string>
<string name="recovery_factory_data_reset" msgid="7321351565602894783">"Tilbakestill til fabrikkstandard"</string>
<string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Vil du viske ut alle brukerdataene?\n\n DETTE KAN IKKE ANGRES!"</string>
<string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Avbryt"</string>
diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml
index 38ca6127..57470752 100644
--- a/tools/recovery_l10n/res/values-te/strings.xml
+++ b/tools/recovery_l10n/res/values-te/strings.xml
@@ -10,5 +10,5 @@
<string name="recovery_try_again" msgid="7168248750158873496">"మళ్లీ ప్రయత్నించు"</string>
<string name="recovery_factory_data_reset" msgid="7321351565602894783">"ఫ్యాక్టరీ డేటా రీసెట్"</string>
<string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"వినియోగదారు డేటా మొత్తాన్ని తొలగించాలా?\n\n ఈ చర్యను రద్దు చేయలేరు!"</string>
- <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయి"</string>
+ <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయండి"</string>
</resources>
diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp
index ff2eff90..220b007f 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 c6f2dad2..b1396a43 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: