Merge "Add an ABI dump directory for libutils"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 46190f2..f1b82e9 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -129,23 +129,23 @@
};
struct Image {
- const char* nickname;
- const char* img_name;
- const char* sig_name;
- const char* part_name;
+ std::string nickname;
+ std::string img_name;
+ std::string sig_name;
+ std::string part_name;
bool optional_if_no_image;
ImageType type;
- bool IsSecondary() const { return nickname == nullptr; }
+ bool IsSecondary() const { return nickname.empty(); }
};
-static Image images[] = {
+static std::vector<Image> images = {
// clang-format off
{ "boot", "boot.img", "boot.sig", "boot", false, ImageType::BootCritical },
{ "init_boot",
"init_boot.img", "init_boot.sig",
"init_boot",
true, ImageType::BootCritical },
- { nullptr, "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
+ { "", "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
{ "cache", "cache.img", "cache.sig", "cache", true, ImageType::Extra },
{ "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
{ "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
@@ -164,7 +164,7 @@
"system_ext.img", "system_ext.sig",
"system_ext",
true, ImageType::Normal },
- { nullptr, "system_other.img", "system.sig", "system", true, ImageType::Normal },
+ { "", "system_other.img", "system.sig", "system", true, ImageType::Normal },
{ "userdata", "userdata.img", "userdata.sig", "userdata", true, ImageType::Extra },
{ "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, ImageType::BootCritical },
{ "vbmeta_system",
@@ -191,7 +191,7 @@
"vendor_kernel_boot.sig",
"vendor_kernel_boot",
true, ImageType::BootCritical },
- { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
+ { "", "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
@@ -212,8 +212,8 @@
}
static std::string find_item(const std::string& item) {
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && item == images[i].nickname) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && item == images[i].nickname) {
return find_item_given_name(images[i].img_name);
}
}
@@ -274,7 +274,8 @@
// require matching serial number or device path if requested
// at the command line with the -s option.
if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
- strcmp(local_serial, info->device_path) != 0)) return -1;
+ strcmp(local_serial, info->device_path) != 0))
+ return -1;
return 0;
}
@@ -532,15 +533,15 @@
std::vector<char> dtb_data;
if (!g_dtb_path.empty()) {
if (g_boot_img_hdr.header_version != 2) {
- die("Argument dtb not supported for boot image header version %d\n",
- g_boot_img_hdr.header_version);
+ die("Argument dtb not supported for boot image header version %d\n",
+ g_boot_img_hdr.header_version);
}
if (!ReadFileToVector(g_dtb_path, &dtb_data)) {
die("cannot load '%s': %s", g_dtb_path.c_str(), strerror(errno));
}
}
- fprintf(stderr,"creating boot image...\n");
+ fprintf(stderr, "creating boot image...\n");
std::vector<char> out;
mkbootimg(kernel_data, ramdisk_data, second_stage_data, dtb_data, g_base_addr, g_boot_img_hdr,
@@ -562,15 +563,15 @@
}
if (zip_entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
- die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
+ die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
}
out->resize(zip_entry.uncompressed_length);
fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(),
out->size() / 1024 / 1024);
- int error = ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()),
- out->size());
+ int error =
+ ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()), out->size());
if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error));
return true;
@@ -618,8 +619,8 @@
std::string path_template(make_temporary_template());
int fd = mkstemp(&path_template[0]);
if (fd == -1) {
- die("failed to create temporary file for %s with template %s: %s\n",
- path_template.c_str(), what, strerror(errno));
+ die("failed to create temporary file for %s with template %s: %s\n", path_template.c_str(),
+ what, strerror(errno));
}
unlink(path_template.c_str());
return fd;
@@ -673,16 +674,15 @@
std::string var_value;
if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) {
fprintf(stderr, "FAILED\n\n");
- fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(),
- fb->Error().c_str());
+ fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb->Error().c_str());
return false;
}
bool match = false;
for (const auto& option : options) {
- if (option == var_value || (option.back() == '*' &&
- !var_value.compare(0, option.length() - 1, option, 0,
- option.length() - 1))) {
+ if (option == var_value ||
+ (option.back() == '*' &&
+ !var_value.compare(0, option.length() - 1, option, 0, option.length() - 1))) {
match = true;
break;
}
@@ -757,8 +757,8 @@
die("device doesn't have required partition %s!", partition_name.c_str());
}
bool known_partition = false;
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && images[i].nickname == partition_name) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && images[i].nickname == partition_name) {
images[i].optional_if_no_image = false;
known_partition = true;
}
@@ -796,9 +796,9 @@
bool met = CheckRequirement(cur_product, name, product, invert, options);
if (!met) {
if (!force_flash) {
- die("requirements not met!");
+ die("requirements not met!");
} else {
- fprintf(stderr, "requirements not met! but proceeding due to --force\n");
+ fprintf(stderr, "requirements not met! but proceeding due to --force\n");
}
}
}
@@ -822,7 +822,6 @@
DisplayVarOrError("Baseband Version.....", "version-baseband");
DisplayVarOrError("Serial Number........", "serialno");
fprintf(stderr, "--------------------------------------------\n");
-
}
static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
@@ -830,13 +829,14 @@
if (!s) die("cannot sparse read file");
if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
- die("invalid max size %" PRId64, max_size);
+ die("invalid max size %" PRId64, max_size);
}
int files = sparse_file_resparse(s, max_size, nullptr, 0);
if (files < 0) die("Failed to resparse");
- sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
+ sparse_file** out_s =
+ reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file*), files + 1));
if (!out_s) die("Failed to allocate sparse file array");
files = sparse_file_resparse(s, max_size, out_s, files);
@@ -1078,8 +1078,7 @@
lseek(buf->fd.get(), 0, SEEK_SET);
}
-static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
-{
+static void flash_buf(const std::string& partition, struct fastboot_buffer* buf) {
sparse_file** s;
if (partition == "boot" || partition == "boot_a" || partition == "boot_b" ||
@@ -1097,7 +1096,7 @@
rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
} else if (!has_vbmeta_partition() &&
(partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
- rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+ rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */);
}
}
@@ -1143,14 +1142,14 @@
}
static bool supports_AB() {
- return get_slot_count() >= 2;
+ return get_slot_count() >= 2;
}
// Given a current slot, this returns what the 'other' slot is.
static std::string get_other_slot(const std::string& current_slot, int count) {
if (count == 0) return "";
- char next = (current_slot[0] - 'a' + 1)%count + 'a';
+ char next = (current_slot[0] - 'a' + 1) % count + 'a';
return std::string(1, next);
}
@@ -1185,17 +1184,17 @@
if (count == 0) die("Device does not support slots");
if (slot == "other") {
- std::string other = get_other_slot( count);
+ std::string other = get_other_slot(count);
if (other == "") {
- die("No known slots");
+ die("No known slots");
}
return other;
}
- if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
+ if (slot.size() == 1 && (slot[0] - 'a' >= 0 && slot[0] - 'a' < count)) return slot;
fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
fprintf(stderr, "%c\n", (char)(i + 'a'));
}
@@ -1203,7 +1202,7 @@
}
static std::string verify_slot(const std::string& slot) {
- return verify_slot(slot, true);
+ return verify_slot(slot, true);
}
static void do_for_partition(const std::string& part, const std::string& slot,
@@ -1243,7 +1242,8 @@
* partition does not support slots.
*/
static void do_for_partitions(const std::string& part, const std::string& slot,
- const std::function<void(const std::string&)>& func, bool force_slot) {
+ const std::function<void(const std::string&)>& func,
+ bool force_slot) {
std::string has_slot;
// |part| can be vendor_boot:default. Query has-slot on the first token only.
auto part_tokens = android::base::Split(part, ":");
@@ -1254,7 +1254,7 @@
slot.c_str());
}
if (has_slot == "yes") {
- for (int i=0; i < get_slot_count(); i++) {
+ for (int i = 0; i < get_slot_count(); i++) {
do_for_partition(part, std::string(1, (char)(i + 'a')), func, force_slot);
}
} else {
@@ -1403,7 +1403,7 @@
class ImageSource {
public:
- virtual ~ImageSource() {};
+ virtual ~ImageSource(){};
virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
virtual unique_fd OpenFile(const std::string& name) const = 0;
};
@@ -1435,13 +1435,11 @@
FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
bool skip_secondary, bool wipe, bool force_flash)
- : source_(source),
- slot_override_(slot_override),
- skip_secondary_(skip_secondary),
- wipe_(wipe),
- force_flash_(force_flash)
-{
-}
+ : source_(source),
+ slot_override_(slot_override),
+ skip_secondary_(skip_secondary),
+ wipe_(wipe),
+ force_flash_(force_flash) {}
void FlashAllTool::Flash() {
DumpInfo();
@@ -1508,7 +1506,7 @@
}
void FlashAllTool::CollectImages() {
- for (size_t i = 0; i < arraysize(images); ++i) {
+ for (size_t i = 0; i < images.size(); ++i) {
std::string slot = slot_override_;
if (images[i].IsSecondary()) {
if (skip_secondary_) {
@@ -1532,7 +1530,7 @@
if (image->optional_if_no_image) {
continue;
}
- die("could not load '%s': %s", image->img_name, strerror(errno));
+ die("could not load '%s': %s", image->img_name.c_str(), strerror(errno));
}
FlashImage(*image, slot, &buf);
}
@@ -1734,8 +1732,7 @@
fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
return;
}
- die("Formatting is not supported for file system with type '%s'.",
- partition_type.c_str());
+ die("Formatting is not supported for file system with type '%s'.", partition_type.c_str());
}
int64_t size;
@@ -1892,32 +1889,30 @@
g_boot_img_hdr.page_size = 2048;
g_boot_img_hdr.dtb_addr = 0x01100000;
- const struct option longopts[] = {
- {"base", required_argument, 0, 0},
- {"cmdline", required_argument, 0, 0},
- {"disable-verification", no_argument, 0, 0},
- {"disable-verity", no_argument, 0, 0},
- {"force", no_argument, 0, 0},
- {"fs-options", required_argument, 0, 0},
- {"header-version", required_argument, 0, 0},
- {"help", no_argument, 0, 'h'},
- {"kernel-offset", required_argument, 0, 0},
- {"os-patch-level", required_argument, 0, 0},
- {"os-version", required_argument, 0, 0},
- {"page-size", required_argument, 0, 0},
- {"ramdisk-offset", required_argument, 0, 0},
- {"set-active", optional_argument, 0, 'a'},
- {"skip-reboot", no_argument, 0, 0},
- {"skip-secondary", no_argument, 0, 0},
- {"slot", required_argument, 0, 0},
- {"tags-offset", required_argument, 0, 0},
- {"dtb", required_argument, 0, 0},
- {"dtb-offset", required_argument, 0, 0},
- {"unbuffered", no_argument, 0, 0},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 0},
- {0, 0, 0, 0}
- };
+ const struct option longopts[] = {{"base", required_argument, 0, 0},
+ {"cmdline", required_argument, 0, 0},
+ {"disable-verification", no_argument, 0, 0},
+ {"disable-verity", no_argument, 0, 0},
+ {"force", no_argument, 0, 0},
+ {"fs-options", required_argument, 0, 0},
+ {"header-version", required_argument, 0, 0},
+ {"help", no_argument, 0, 'h'},
+ {"kernel-offset", required_argument, 0, 0},
+ {"os-patch-level", required_argument, 0, 0},
+ {"os-version", required_argument, 0, 0},
+ {"page-size", required_argument, 0, 0},
+ {"ramdisk-offset", required_argument, 0, 0},
+ {"set-active", optional_argument, 0, 'a'},
+ {"skip-reboot", no_argument, 0, 0},
+ {"skip-secondary", no_argument, 0, 0},
+ {"slot", required_argument, 0, 0},
+ {"tags-offset", required_argument, 0, 0},
+ {"dtb", required_argument, 0, 0},
+ {"dtb-offset", required_argument, 0, 0},
+ {"unbuffered", no_argument, 0, 0},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 0},
+ {0, 0, 0, 0}};
serial = getenv("ANDROID_SERIAL");
@@ -1966,7 +1961,8 @@
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
} else if (name == "version") {
- fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION, android::build::GetBuildNumber().c_str());
+ fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION,
+ android::build::GetBuildNumber().c_str());
fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
return 0;
} else {
@@ -2024,9 +2020,9 @@
return 1;
}
fastboot::DriverCallbacks driver_callbacks = {
- .prolog = Status,
- .epilog = Epilog,
- .info = InfoMessage,
+ .prolog = Status,
+ .epilog = Epilog,
+ .info = InfoMessage,
};
fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
fb = &fastboot_driver;
@@ -2063,7 +2059,8 @@
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
std::string partition_type;
- if (fb->GetVar("partition-type:" + partition, &partition_type) == fastboot::SUCCESS &&
+ if (fb->GetVar("partition-type:" + partition, &partition_type) ==
+ fastboot::SUCCESS &&
fs_get_generator(partition_type) != nullptr) {
fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
partition_type.c_str());
@@ -2118,7 +2115,6 @@
} else {
syntax_error("unknown reboot target %s", what.c_str());
}
-
}
if (!args.empty()) syntax_error("junk after reboot command");
} else if (command == FB_CMD_REBOOT_BOOTLOADER) {
@@ -2149,7 +2145,7 @@
}
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
- auto flash = [&](const std::string &partition) {
+ auto flash = [&](const std::string& partition) {
if (should_flash_in_userspace(partition) && !is_userspace_fastboot() &&
!force_flash) {
die("The partition you are trying to flash is dynamic, and "
@@ -2178,7 +2174,8 @@
do_for_partitions(partition, slot_override, flashraw, true);
} else if (command == "flashall") {
if (slot_override == "all") {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
do_flashall(slot_override, true, wants_wipe, force_flash);
} else {
do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
@@ -2187,7 +2184,8 @@
} else if (command == "update") {
bool slot_all = (slot_override == "all");
if (slot_all) {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
}
std::string filename = "update.zip";
if (!args.empty()) {
@@ -2214,10 +2212,9 @@
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
- } else if (args.size() == 1 && (args[0] == "unlock" || args[0] == "lock" ||
- args[0] == "unlock_critical" ||
- args[0] == "lock_critical" ||
- args[0] == "get_unlock_ability")) {
+ } else if (args.size() == 1 &&
+ (args[0] == "unlock" || args[0] == "lock" || args[0] == "unlock_critical" ||
+ args[0] == "lock_critical" || args[0] == "get_unlock_ability")) {
do_oem_command("flashing", &args);
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
@@ -2272,7 +2269,7 @@
if (force_flash) {
CancelSnapshotIfNeeded();
}
- std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+ std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
for (const auto& partition : partitions) {
std::string partition_type;
if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
@@ -2334,8 +2331,7 @@
unsigned fsOptions = 0;
std::vector<std::string> options = android::base::Split(arg, ",");
- if (options.size() < 1)
- syntax_error("bad options: %s", arg);
+ if (options.size() < 1) syntax_error("bad options: %s", arg);
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == "casefold")
diff --git a/fs_mgr/tools/dmuserd.cpp b/fs_mgr/tools/dmuserd.cpp
index 6b68b28..da7156c 100644
--- a/fs_mgr/tools/dmuserd.cpp
+++ b/fs_mgr/tools/dmuserd.cpp
@@ -13,6 +13,7 @@
#include <sys/prctl.h>
#include <unistd.h>
#include <iostream>
+#include <string>
#define SECTOR_SIZE ((__u64)512)
#define BUFFER_BYTES 4096
@@ -133,16 +134,16 @@
return 0;
}
-int simple_daemon(char* control_path, char* backing_path) {
- int control_fd = open(control_path, O_RDWR);
+static int simple_daemon(const std::string& control_path, const std::string& backing_path) {
+ int control_fd = open(control_path.c_str(), O_RDWR);
if (control_fd < 0) {
- fprintf(stderr, "Unable to open control device %s\n", control_path);
+ fprintf(stderr, "Unable to open control device %s\n", control_path.c_str());
return -1;
}
- int backing_fd = open(backing_path, O_RDWR);
+ int backing_fd = open(backing_path.c_str(), O_RDWR);
if (backing_fd < 0) {
- fprintf(stderr, "Unable to open backing device %s\n", backing_path);
+ fprintf(stderr, "Unable to open backing device %s\n", backing_path.c_str());
return -1;
}
@@ -286,8 +287,8 @@
}
int main(int argc, char* argv[]) {
- char* control_path = NULL;
- char* backing_path = NULL;
+ std::string control_path;
+ std::string backing_path;
char* store;
int c;
@@ -299,10 +300,10 @@
usage(basename(argv[0]));
exit(0);
case 'c':
- control_path = strdup(optarg);
+ control_path = optarg;
break;
case 'b':
- backing_path = strdup(optarg);
+ backing_path = optarg;
break;
case 'v':
verbose = true;
diff --git a/init/Android.bp b/init/Android.bp
index 06f696e..c7e7de8 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -109,21 +109,22 @@
misc_undefined: ["signed-integer-overflow"],
},
cflags: [
- "-DLOG_UEVENTS=0",
- "-Wall",
- "-Wextra",
- "-Wno-unused-parameter",
- "-Werror",
- "-Wthread-safety",
"-DALLOW_FIRST_STAGE_CONSOLE=0",
"-DALLOW_LOCAL_PROP_OVERRIDE=0",
"-DALLOW_PERMISSIVE_SELINUX=0",
- "-DREBOOT_BOOTLOADER_ON_PANIC=0",
- "-DWORLD_WRITABLE_KMSG=0",
+ "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
"-DDUMP_ON_UMOUNT_FAILURE=0",
- "-DSHUTDOWN_ZERO_TIMEOUT=0",
"-DINIT_FULL_SOURCES",
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=0",
+ "-DLOG_UEVENTS=0",
+ "-DREBOOT_BOOTLOADER_ON_PANIC=0",
+ "-DSHUTDOWN_ZERO_TIMEOUT=0",
+ "-DWORLD_WRITABLE_KMSG=0",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
],
product_variables: {
debuggable: {
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 7cb8b11..a89813e 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -331,13 +331,13 @@
unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)));
if (s < 0) return ErrnoError() << "opening socket failed";
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+ if (ioctl(s.get(), SIOCGIFFLAGS, &ifr) < 0) {
return ErrnoError() << "ioctl(..., SIOCGIFFLAGS, ...) failed";
}
ifr.ifr_flags |= IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+ if (ioctl(s.get(), SIOCSIFFLAGS, &ifr) < 0) {
return ErrnoError() << "ioctl(..., SIOCSIFFLAGS, ...) failed";
}
@@ -516,11 +516,11 @@
loop_info info;
/* if it is a blank loop device */
- if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
+ if (ioctl(loop.get(), LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
/* if it becomes our loop device */
- if (ioctl(loop, LOOP_SET_FD, fd.get()) >= 0) {
+ if (ioctl(loop.get(), LOOP_SET_FD, fd.get()) >= 0) {
if (mount(tmp.c_str(), target, system, flags, options) < 0) {
- ioctl(loop, LOOP_CLR_FD, 0);
+ ioctl(loop.get(), LOOP_CLR_FD, 0);
return ErrnoError() << "mount() failed";
}
return {};
@@ -901,16 +901,16 @@
if (fd == -1) {
return ErrnoError() << "Error opening file";
}
- if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED)) {
+ if (posix_fadvise(fd.get(), 0, 0, POSIX_FADV_WILLNEED)) {
return ErrnoError() << "Error posix_fadvise file";
}
- if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
+ if (readahead(fd.get(), 0, std::numeric_limits<size_t>::max())) {
return ErrnoError() << "Error readahead file";
}
if (fully) {
char buf[BUFSIZ];
ssize_t n;
- while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+ while ((n = TEMP_FAILURE_RETRY(read(fd.get(), &buf[0], sizeof(buf)))) > 0) {
}
if (n != 0) {
return ErrnoError() << "Error reading file";
diff --git a/init/epoll.cpp b/init/epoll.cpp
index fd1af4f..cd73a0c 100644
--- a/init/epoll.cpp
+++ b/init/epoll.cpp
@@ -57,7 +57,7 @@
.events = events,
.data.fd = fd,
};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, fd, &ev) == -1) {
Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";
epoll_handlers_.erase(fd);
return result;
@@ -66,7 +66,7 @@
}
Result<void> Epoll::UnregisterHandler(int fd) {
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, fd, nullptr) == -1) {
return ErrnoError() << "epoll_ctl failed to remove fd";
}
auto it = epoll_handlers_.find(fd);
@@ -88,7 +88,7 @@
}
const auto max_events = epoll_handlers_.size();
epoll_event ev[max_events];
- auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, ev, max_events, timeout_ms));
+ auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), ev, max_events, timeout_ms));
if (num_events == -1) {
return ErrnoError() << "epoll_wait failed";
}
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 30e808d..b9fa58c 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -257,12 +257,12 @@
return false;
}
struct stat sb;
- if (fstat(fw_fd, &sb) == -1) {
+ if (fstat(fw_fd.get(), &sb) == -1) {
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
", fstat failed: " + strerror(errno));
return false;
}
- LoadFirmware(firmware, root, fw_fd, sb.st_size, loading_fd, data_fd);
+ LoadFirmware(firmware, root, fw_fd.get(), sb.st_size, loading_fd.get(), data_fd.get());
return true;
};
@@ -287,7 +287,7 @@
}
// Write "-1" as our response to the kernel's firmware request, since we have nothing for it.
- write(loading_fd, "-1", 2);
+ write(loading_fd.get(), "-1", 2);
}
bool FirmwareHandler::ForEachFirmwareDirectory(
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index d33a6b8..8db7267 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -77,7 +77,7 @@
}
struct stat sb;
- if (fstat(fd, &sb) == -1) {
+ if (fstat(fd.get(), &sb) == -1) {
PLOG(ERROR) << "fstat on property file \"" << entry->d_name << "\" failed";
continue;
}
@@ -198,7 +198,7 @@
if (!WriteStringToFd(serialized_string, fd)) {
return ErrnoError() << "Unable to write file contents";
}
- fsync(fd);
+ fsync(fd.get());
fd.reset();
if (rename(temp_filename.c_str(), persistent_property_filename.c_str())) {
@@ -216,7 +216,7 @@
if (dir_fd < 0) {
return ErrnoError() << "Unable to open persistent properties directory for fsync()";
}
- fsync(dir_fd);
+ fsync(dir_fd.get());
return {};
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 22b66a9..9df9828 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -300,13 +300,13 @@
if (!socket_.ok()) {
return true;
}
- int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0));
+ int result = TEMP_FAILURE_RETRY(send(socket_.get(), &value, sizeof(value), 0));
return result == sizeof(value);
}
bool GetSourceContext(std::string* source_context) const {
char* c_source_context = nullptr;
- if (getpeercon(socket_, &c_source_context) != 0) {
+ if (getpeercon(socket_.get(), &c_source_context) != 0) {
return false;
}
*source_context = c_source_context;
@@ -321,7 +321,7 @@
private:
bool PollIn(uint32_t* timeout_ms) {
struct pollfd ufd = {
- .fd = socket_,
+ .fd = socket_.get(),
.events = POLLIN,
};
while (*timeout_ms > 0) {
@@ -368,7 +368,7 @@
return false;
}
- int result = TEMP_FAILURE_RETRY(recv(socket_, data, bytes_left, MSG_DONTWAIT));
+ int result = TEMP_FAILURE_RETRY(recv(socket_.get(), data, bytes_left, MSG_DONTWAIT));
if (result <= 0) {
PLOG(ERROR) << "sys_prop: recv error";
return false;
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 1f4186d..a3fc534 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -767,7 +767,7 @@
if (IsDataMounted("f2fs")) {
uint32_t flag = F2FS_GOING_DOWN_FULLSYNC;
unique_fd fd(TEMP_FAILURE_RETRY(open("/data", O_RDONLY)));
- int ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag);
+ int ret = ioctl(fd.get(), F2FS_IOC_SHUTDOWN, &flag);
if (ret) {
PLOG(ERROR) << "Shutdown /data: ";
} else {
diff --git a/init/security.cpp b/init/security.cpp
index 2ecf687..6e616be 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -216,7 +216,7 @@
return {};
}
- int ioctl_ret = ioctl(fd, PERF_EVENT_IOC_RESET);
+ int ioctl_ret = ioctl(fd.get(), PERF_EVENT_IOC_RESET);
if (ioctl_ret != -1) {
// Success implies that the kernel doesn't have the hooks.
return {};
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ab5b0a0..ea308aa 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -567,7 +567,7 @@
return ErrnoError() << "Failed to open " << dstPath;
}
- ret = ExtractEntryToFile(archive, &entry, fd);
+ ret = ExtractEntryToFile(archive, &entry, fd.get());
if (ret != 0) {
return Error() << "Failed to extract entry \"" << fileName << "\" ("
<< entry.uncompressed_length << " bytes) to \"" << dstPath
@@ -785,7 +785,7 @@
return;
}
- TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0));
+ TEMP_FAILURE_RETRY(send(fd.get(), &request, sizeof(request), 0));
}
} // namespace
diff --git a/init/service.h b/init/service.h
index 6fb2804..f9749d2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -73,6 +73,8 @@
const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
Subcontext* subcontext_for_restart_commands, const std::string& filename,
const std::vector<std::string>& args);
+ Service(const Service&) = delete;
+ void operator=(const Service&) = delete;
static Result<std::unique_ptr<Service>> MakeTemporaryOneshotService(
const std::vector<std::string>& args);
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index 15bf963..7004d8d 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -52,7 +52,7 @@
if (fd == -1) {
return ErrnoError() << "Could not open namespace at " << path;
}
- if (setns(fd, nstype) == -1) {
+ if (setns(fd.get(), nstype) == -1) {
return ErrnoError() << "Could not setns() namespace at " << path;
}
return {};
@@ -127,22 +127,22 @@
void SetupStdio(bool stdio_to_kmsg) {
auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
- dup2(fd, STDIN_FILENO);
+ dup2(fd.get(), STDIN_FILENO);
if (stdio_to_kmsg) {
fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC));
if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
}
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
+ dup2(fd.get(), STDOUT_FILENO);
+ dup2(fd.get(), STDERR_FILENO);
}
void OpenConsole(const std::string& console) {
auto fd = unique_fd{open(console.c_str(), O_RDWR | O_CLOEXEC)};
if (fd == -1) fd.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
- ioctl(fd, TIOCSCTTY, 0);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
+ ioctl(fd.get(), TIOCSCTTY, 0);
+ dup2(fd.get(), 0);
+ dup2(fd.get(), 1);
+ dup2(fd.get(), 2);
}
} // namespace
@@ -190,7 +190,7 @@
}
// Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
- fcntl(fd, F_SETFL, flags);
+ fcntl(fd.get(), F_SETFL, flags);
return Descriptor(ANDROID_FILE_ENV_PREFIX + name, std::move(fd));
}
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 961e006..6a095fb 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -207,7 +207,7 @@
// We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
// in the subcontext process after we exec.
- int child_fd = dup(subcontext_socket); // NOLINT(android-cloexec-dup)
+ int child_fd = dup(subcontext_socket.get()); // NOLINT(android-cloexec-dup)
if (child_fd < 0) {
PLOG(FATAL) << "Could not dup child_fd";
}
@@ -268,12 +268,12 @@
}
Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
- if (auto result = SendMessage(socket_, subcontext_command); !result.ok()) {
+ if (auto result = SendMessage(socket_.get(), subcontext_command); !result.ok()) {
Restart();
return ErrnoError() << "Failed to send message to subcontext";
}
- auto subcontext_message = ReadMessage(socket_);
+ auto subcontext_message = ReadMessage(socket_.get());
if (!subcontext_message.ok()) {
Restart();
return Error() << "Failed to receive result from subcontext: " << subcontext_message.error();
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 10af06b..3188337 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -22,6 +22,7 @@
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
+#include <memory>
int MaybeDowngrade() {
int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
@@ -58,7 +59,7 @@
// Disallow automatic upgrade from ASYNC mode.
if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
}
- volatile char* f = (char*)malloc(1);
+ std::unique_ptr<volatile char[]> f(new char[1]);
f[17] = 'x';
char buf[1];
read(1, buf, 1);
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 7cd396a..5da6777 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -92,12 +92,12 @@
LOG(FATAL) << "Could not open uevent socket";
}
- fcntl(device_fd_, F_SETFL, O_NONBLOCK);
+ fcntl(device_fd_.get(), F_SETFL, O_NONBLOCK);
}
ReadUeventResult UeventListener::ReadUevent(Uevent* uevent) const {
char msg[UEVENT_MSG_LEN + 2];
- int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN);
+ int n = uevent_kernel_multicast_recv(device_fd_.get(), msg, UEVENT_MSG_LEN);
if (n <= 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
PLOG(ERROR) << "Error reading from Uevent Fd";
@@ -184,9 +184,10 @@
const std::optional<std::chrono::milliseconds> relative_timeout) const {
using namespace std::chrono;
- pollfd ufd;
- ufd.events = POLLIN;
- ufd.fd = device_fd_;
+ pollfd ufd = {
+ .events = POLLIN,
+ .fd = device_fd_.get(),
+ };
auto start_time = steady_clock::now();
diff --git a/init/util.cpp b/init/util.cpp
index 3d42855..bc8ea6e 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -120,12 +120,12 @@
if (passcred) {
int on = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
+ if (setsockopt(fd.get(), SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
return ErrnoError() << "Failed to set SO_PASSCRED '" << name << "'";
}
}
- int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
+ int ret = bind(fd.get(), (struct sockaddr*)&addr, sizeof(addr));
int savederrno = errno;
if (!secontext.empty()) {
@@ -145,7 +145,7 @@
if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
return ErrnoError() << "Failed to fchmodat socket '" << addr.sun_path << "'";
}
- if (should_listen && listen(fd, /* use OS maximum */ 1 << 30)) {
+ if (should_listen && listen(fd.get(), /* use OS maximum */ 1 << 30)) {
return ErrnoError() << "Failed to listen on socket '" << addr.sun_path << "'";
}
@@ -168,7 +168,7 @@
// For security reasons, disallow world-writable
// or group-writable files.
struct stat sb;
- if (fstat(fd, &sb) == -1) {
+ if (fstat(fd.get(), &sb) == -1) {
return ErrnoError() << "fstat failed()";
}
if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
diff --git a/libsystem/include/system/graphics-base-v1.2.h b/libsystem/include/system/graphics-base-v1.2.h
index 2194f5e..624912c 100644
--- a/libsystem/include/system/graphics-base-v1.2.h
+++ b/libsystem/include/system/graphics-base-v1.2.h
@@ -14,13 +14,17 @@
} android_hdr_v1_2_t;
typedef enum {
- HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* ((STANDARD_BT2020 | TRANSFER_SRGB) | RANGE_FULL) */,
+ HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL */,
HAL_DATASPACE_DYNAMIC_DEPTH = 4098 /* 0x1002 */,
HAL_DATASPACE_JPEG_APP_SEGMENTS = 4099 /* 0x1003 */,
HAL_DATASPACE_HEIF = 4100 /* 0x1004 */,
} android_dataspace_v1_2_t;
typedef enum {
+ HAL_COLOR_MODE_DISPLAY_BT2020 = 13,
+} android_color_mode_v1_2_t;
+
+typedef enum {
HAL_PIXEL_FORMAT_HSV_888 = 55 /* 0x37 */,
} android_pixel_format_v1_2_t;
diff --git a/libutils/Unicode_test.cpp b/libutils/Unicode_test.cpp
index 8b994d9..7969525 100644
--- a/libutils/Unicode_test.cpp
+++ b/libutils/Unicode_test.cpp
@@ -35,86 +35,208 @@
}
char16_t const * const kSearchString = u"I am a leaf on the wind.";
+
+ constexpr static size_t BUFSIZE = 64; // large enough for all tests
+
+ void TestUTF8toUTF16(std::initializer_list<uint8_t> input,
+ std::initializer_list<char16_t> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ uint8_t empty_str[] = {};
+ char16_t output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const uint8_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf8_to_utf16_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf8_to_utf16(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
+
+ void TestUTF16toUTF8(std::initializer_list<char16_t> input,
+ std::initializer_list<char> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ char16_t empty_str[] = {};
+ char output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const char16_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf16_to_utf8_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf16_to_utf8(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
};
TEST_F(UnicodeTest, UTF8toUTF16ZeroLength) {
- ssize_t measured;
-
- const uint8_t str[] = { };
-
- measured = utf8_to_utf16_length(str, 0);
- EXPECT_EQ(0, measured)
- << "Zero length input should return zero length output.";
+ TestUTF8toUTF16({}, {},
+ "Zero length input should return zero length output.");
}
-TEST_F(UnicodeTest, UTF8toUTF16ASCIILength) {
- ssize_t measured;
-
- // U+0030 or ASCII '0'
- const uint8_t str[] = { 0x30 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "ASCII glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16ASCII) {
+ TestUTF8toUTF16(
+ { 0x30 }, // U+0030 or ASCII '0'
+ { 0x0030 },
+ "ASCII codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16Plane1Length) {
- ssize_t measured;
-
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C, 0xA3 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "Plane 1 glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Plane1) {
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C, 0xA3 }, // U+2323 SMILE
+ { 0x2323 },
+ "Plane 1 codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16SurrogateLength) {
- ssize_t measured;
-
- // U+10000
- const uint8_t str[] = { 0xF0, 0x90, 0x80, 0x80 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(2, measured)
- << "Surrogate pairs should have a length of 2 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Surrogate) {
+ TestUTF8toUTF16(
+ { 0xF0, 0x90, 0x80, 0x80 }, // U+10000
+ { 0xD800, 0xDC00 },
+ "Surrogate pairs should have a length of 2 char16_t");
}
TEST_F(UnicodeTest, UTF8toUTF16TruncatedUTF8) {
- ssize_t measured;
-
- // Truncated U+2323 SMILE
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(-1, measured)
- << "Truncated UTF-8 should return -1 to indicate invalid";
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C }, // Truncated U+2323 SMILE
+ { }, // Conversion should still work but produce nothing
+ "Truncated UTF-8 should return -1 to indicate invalid",
+ -1);
}
TEST_F(UnicodeTest, UTF8toUTF16Normal) {
- const uint8_t str[] = {
- 0x30, // U+0030, 1 UTF-16 character
- 0xC4, 0x80, // U+0100, 1 UTF-16 character
- 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
+ TestUTF8toUTF16({
+ 0x30, // U+0030, 1 UTF-16 character
+ 0xC4, 0x80, // U+0100, 1 UTF-16 character
+ 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
0xF0, 0x90, 0x80, 0x80, // U+10000, 2 UTF-16 character
- };
+ }, {
+ 0x0030,
+ 0x0100,
+ 0x2323,
+ 0xD800, 0xDC00
+ });
+}
- char16_t output[1 + 1 + 1 + 2 + 1]; // Room for null
+TEST_F(UnicodeTest, UTF8toUTF16Invalid) {
+ // TODO: The current behavior of utf8_to_utf16 is to treat invalid
+ // leading byte (>= 0xf8) as a 4-byte UTF8 sequence, and to treat
+ // invalid trailing byte(s) (i.e. bytes not having MSB set) as if
+ // they are valid and do the normal conversion. However, a better
+ // handling would be to treat invalid sequences as errors, such
+ // cases need to be reported and invalid characters (e.g. U+FFFD)
+ // could be produced at the place of error. Until a fix is ready
+ // and compatibility is not an issue, we will keep testing the
+ // current behavior
+ TestUTF8toUTF16({
+ 0xf8, // invalid leading byte
+ 0xc4, 0x00, // U+0100 with invalid trailing byte
+ 0xe2, 0x0c, 0xa3, // U+2323 with invalid trailing bytes
+ 0xf0, 0x10, 0x00, 0x00, // U+10000 with invalid trailing bytes
+ }, {
+ 0x4022, // invalid leading byte (>=0xfc) is treated
+ // as valid for 4-byte UTF8 sequence
+ 0x000C,
+ 0x00A3, // invalid leadnig byte (b'10xxxxxx) is
+ // treated as valid single UTF-8 byte
+ 0xD800, // invalid trailing bytes are treated
+ 0xDC00, // as valid bytes and follow normal
+ });
+}
- utf8_to_utf16(str, sizeof(str), output, sizeof(output) / sizeof(output[0]));
+TEST_F(UnicodeTest, UTF16toUTF8ZeroLength) {
+ // TODO: The current behavior of utf16_to_utf8_length() is that
+ // it returns -1 if the input is a zero length UTF16 string.
+ // This is inconsistent with utf8_to_utf16_length() where a zero
+ // length string returns 0. However, to fix the current behavior,
+ // we could have compatibility issue. Until then, we will keep
+ // testing the current behavior
+ TestUTF16toUTF8({}, {},
+ "Zero length UTF16 input should return length of -1.", -1);
+}
- EXPECT_EQ(0x0030, output[0])
- << "should be U+0030";
- EXPECT_EQ(0x0100, output[1])
- << "should be U+0100";
- EXPECT_EQ(0x2323, output[2])
- << "should be U+2323";
- EXPECT_EQ(0xD800, output[3])
- << "should be first half of surrogate U+10000";
- EXPECT_EQ(0xDC00, output[4])
- << "should be second half of surrogate U+10000";
- EXPECT_EQ(0, output[5]) << "should be null terminated";
+TEST_F(UnicodeTest, UTF16toUTF8ASCII) {
+ TestUTF16toUTF8(
+ { 0x0030 }, // U+0030 or ASCII '0'
+ { '\x30' },
+ "ASCII codepoints in UTF16 should give a length of 1 in UTF8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Plane1) {
+ TestUTF16toUTF8(
+ { 0x2323 }, // U+2323 SMILE
+ { '\xE2', '\x8C', '\xA3' },
+ "Plane 1 codepoints should have a length of 3 char in UTF-8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Surrogate) {
+ TestUTF16toUTF8(
+ { 0xD800, 0xDC00 }, // U+10000
+ { '\xF0', '\x90', '\x80', '\x80' },
+ "Surrogate pairs should have a length of 4 chars");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8UnpairedSurrogate) {
+ TestUTF16toUTF8(
+ { 0xD800 }, // U+10000 with high surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired high surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ { 0xDC00 }, // U+10000 with low surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired low surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired high surrogate should be skipped in the middle");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired low surrogate should be skipped in the middle");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8CorrectInvalidSurrogate) {
+ // http://b/29250543
+ // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the
+ // first character in the pair and handling the rest correctly.
+ TestUTF16toUTF8(
+ { 0xD841, 0xD841, 0xDC41 }, // U+20441
+ { '\xF0', '\xA0', '\x91', '\x81' },
+ "Invalid start for a surrogate pair should be ignored");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Normal) {
+ TestUTF16toUTF8({
+ 0x0024, // U+0024 ($) --> 0x24, 1 UTF-8 byte
+ 0x00A3, // U+00A3 (£) --> 0xC2 0xA3, 2 UTF-8 bytes
+ 0x0939, // U+0939 (ह) --> 0xE0 0xA4 0xB9, 3 UTF-8 bytes
+ 0x20AC, // U+20AC (€) --> 0xE2 0x82 0xAC, 3 UTF-8 bytes
+ 0xD55C, // U+D55C (한)--> 0xED 0x95 0x9C, 3 UTF-8 bytes
+ 0xD801, 0xDC37, // U+10437 (𐐷) --> 0xF0 0x90 0x90 0xB7, 4 UTF-8 bytes
+ }, {
+ '\x24',
+ '\xC2', '\xA3',
+ '\xE0', '\xA4', '\xB9',
+ '\xE2', '\x82', '\xAC',
+ '\xED', '\x95', '\x9C',
+ '\xF0', '\x90', '\x90', '\xB7',
+ });
}
TEST_F(UnicodeTest, strstr16EmptyTarget) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1131f3f..d8e6b55 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -936,16 +936,20 @@
restorecon /data/media
exec - media_rw media_rw -- /system/bin/chattr +F /data/media
- # A tmpfs directory, which will contain all apps CE DE data directory that
- # bind mount from the original source.
+ # A tmpfs directory, which will contain all apps and sdk sandbox CE and DE
+ # data directory that bind mount from the original source.
mount tmpfs tmpfs /data_mirror nodev noexec nosuid mode=0700,uid=0,gid=1000
restorecon /data_mirror
mkdir /data_mirror/data_ce 0700 root root
mkdir /data_mirror/data_de 0700 root root
+ mkdir /data_mirror/misc_ce 0700 root root
+ mkdir /data_mirror/misc_de 0700 root root
# Create CE and DE data directory for default volume
mkdir /data_mirror/data_ce/null 0700 root root
mkdir /data_mirror/data_de/null 0700 root root
+ mkdir /data_mirror/misc_ce/null 0700 root root
+ mkdir /data_mirror/misc_de/null 0700 root root
# Bind mount CE and DE data directory to mirror's default volume directory.
# Note that because the /data mount has the "shared" propagation type, the
@@ -953,6 +957,8 @@
# propagate to /data_mirror/data_ce/null/0 as well.
mount none /data/user /data_mirror/data_ce/null bind rec
mount none /data/user_de /data_mirror/data_de/null bind rec
+ mount none /data/misc_ce /data_mirror/misc_ce/null bind rec
+ mount none /data/misc_de /data_mirror/misc_de/null bind rec
# Create mirror directory for jit profiles
mkdir /data_mirror/cur_profiles 0700 root root
diff --git a/trusty/keymint/Android.bp b/trusty/keymint/Android.bp
new file mode 100644
index 0000000..c19ebbd
--- /dev/null
+++ b/trusty/keymint/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2022 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary {
+ name: "android.hardware.security.keymint-service.rust.trusty",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.security.keymint-service.rust.trusty.rc"],
+ vintf_fragments: ["android.hardware.security.keymint-service.rust.trusty.xml"],
+ srcs: [
+ "src/keymint_hal_main.rs"
+ ],
+ rustlibs: [
+ "libandroid_logger",
+ "libbinder_rs",
+ "libkmr_wire",
+ "libkmr_hal",
+ "libtrusty-rs",
+ "liblibc",
+ "liblog_rust",
+ ],
+ required: [
+ "android.hardware.hardware_keystore.xml",
+ ],
+}
diff --git a/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
new file mode 100644
index 0000000..cd656b2
--- /dev/null
+++ b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<permissions>
+ <feature name="android.hardware.hardware_keystore" version="300" />
+</permissions>
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
new file mode 100644
index 0000000..e3d94c6
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
@@ -0,0 +1,7 @@
+service vendor.keymint.rust-trusty /vendor/bin/hw/android.hardware.security.keymint-service.rust.trusty
+ class early_hal
+ user nobody
+ group drmrpc
+ # The keymint service is not allowed to restart.
+ # If it crashes, a device restart is required.
+ oneshot
\ No newline at end of file
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
new file mode 100644
index 0000000..3dc9c88
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <version>3</version>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.secureclock</name>
+ <fqname>ISecureClock/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <version>3</version>
+ <fqname>IRemotelyProvisionedComponent/default</fqname>
+ </hal>
+</manifest>
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
new file mode 100644
index 0000000..d2d5f27
--- /dev/null
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -0,0 +1,155 @@
+//
+// Copyright (C) 2022 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements the HAL service for Keymint (Rust) in Trusty.
+use kmr_hal::{keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel};
+use log::{error, info};
+use std::{
+ ffi::CString,
+ ops::DerefMut,
+ panic,
+ sync::{Arc, Mutex},
+};
+use trusty::DEFAULT_DEVICE;
+
+const TRUSTY_KEYMINT_RUST_SERVICE_NAME: &str = "com.android.trusty.keymint";
+
+static SERVICE_INSTANCE: &str = "default";
+
+static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
+static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent";
+static SECURE_CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+static SHARED_SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+#[derive(Debug)]
+struct TipcChannel(trusty::TipcChannel);
+
+impl SerializedChannel for TipcChannel {
+ fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
+ self.0.send(serialized_req).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to send the request via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ let mut recv_buf = Vec::new();
+ // TODO(b/253501976): cope with fragmentation of responses
+ self.0.recv(&mut recv_buf).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to receive the response via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ Ok(recv_buf)
+ }
+}
+
+fn main() {
+ if let Err(e) = inner_main() {
+ panic!("HAL service failed: {:?}", e);
+ }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+ // Initialize Android logging.
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("keymint-hal-trusty")
+ .with_min_level(log::Level::Info)
+ .with_log_id(android_logger::LogId::System),
+ );
+ // Redirect panic messages to logcat.
+ panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
+ info!("Trusty KM HAL service is starting.");
+
+ info!("Starting thread pool now.");
+ binder::ProcessState::start_thread_pool();
+
+ // Create connection to the TA
+ let connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, TRUSTY_KEYMINT_RUST_SERVICE_NAME)
+ .map_err(|e| {
+ HalServiceError(format!("Failed to connect to Trusty Keymint TA because of {:?}.", e))
+ })?;
+ let tipc_channel = Arc::new(Mutex::new(TipcChannel(connection)));
+
+ // Register the Keymint service
+ let km_service = keymint::Device::new_as_binder(tipc_channel.clone());
+ let km_service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&km_service_name, km_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ km_service_name, e
+ ))
+ })?;
+
+ // Register the Remotely Provisioned Component service
+ let rpc_service = rpc::Device::new_as_binder(tipc_channel.clone());
+ let rpc_service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&rpc_service_name, rpc_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ rpc_service_name, e
+ ))
+ })?;
+
+ // Register the Secure Clock service
+ let sclock_service = secureclock::Device::new_as_binder(tipc_channel.clone());
+ let sclock_service_name = format!("{}/{}", SECURE_CLOCK_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&sclock_service_name, sclock_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ sclock_service_name, e
+ ))
+ })?;
+
+ // Register the Shared Secret service
+ let ssecret_service = sharedsecret::Device::new_as_binder(tipc_channel.clone());
+ let ssecret_service_name = format!("{}/{}", SHARED_SECRET_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&ssecret_service_name, ssecret_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ ssecret_service_name, e
+ ))
+ })?;
+
+ // Send the HAL service information to the TA
+ send_hal_info(tipc_channel.lock().unwrap().deref_mut())
+ .map_err(|e| HalServiceError(format!("Failed to populate HAL info: {:?}", e)))?;
+
+ info!("Successfully registered KeyMint HAL services.");
+ info!("Joining thread pool now.");
+ binder::ProcessState::join_thread_pool();
+ info!("KeyMint HAL service is terminating."); // should not reach here
+ Ok(())
+}