Merge "Add more comments for resolv apex."
diff --git a/.clang-format-2 b/.clang-format-2
deleted file mode 100644
index ede5d7e..0000000
--- a/.clang-format-2
+++ /dev/null
@@ -1,9 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IndentWidth: 2
-PointerAlignment: Left
-TabWidth: 2
-UseTab: Never
diff --git a/.clang-format-2 b/.clang-format-2
new file mode 120000
index 0000000..7ab20d4
--- /dev/null
+++ b/.clang-format-2
@@ -0,0 +1 @@
+../../build/soong/scripts/system-clang-format-2
\ No newline at end of file
diff --git a/.clang-format-4 b/.clang-format-4
deleted file mode 100644
index 55773a2..0000000
--- a/.clang-format-4
+++ /dev/null
@@ -1,11 +0,0 @@
-BasedOnStyle: Google
-AccessModifierOffset: -2
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IndentWidth: 4
-ContinuationIndentWidth: 8
-PointerAlignment: Left
-TabWidth: 4
-UseTab: Never
diff --git a/.clang-format-4 b/.clang-format-4
new file mode 120000
index 0000000..ddcf5a2
--- /dev/null
+++ b/.clang-format-4
@@ -0,0 +1 @@
+../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/adb/Android.bp b/adb/Android.bp
index 8199fff..3813578 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -156,8 +156,6 @@
"client/usb_libusb.cpp",
"client/usb_dispatch.cpp",
"client/transport_mdns.cpp",
- "client/fastdeploy.cpp",
- "client/fastdeploycallbacks.cpp",
],
generated_headers: ["platform_tools_version"],
@@ -192,9 +190,6 @@
"libdiagnose_usb",
"libmdnssd",
"libusb",
- "libandroidfw",
- "libziparchive",
- "libz",
"libutils",
"liblog",
"libcutils",
@@ -280,9 +275,6 @@
"liblog",
"libmdnssd",
"libusb",
- "libandroidfw",
- "libziparchive",
- "libz",
"libutils",
"liblog",
"libcutils",
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index d56a25f..3869945 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -36,7 +36,9 @@
#include "commandline.h"
#include "fastdeploy.h"
+#if defined(ENABLE_FASTDEPLOY)
static constexpr int kFastDeployMinApi = 24;
+#endif
static bool can_use_feature(const char* feature) {
FeatureSet features;
@@ -130,10 +132,12 @@
*buf = '\0';
}
+#if defined(ENABLE_FASTDEPLOY)
static int delete_device_patch_file(const char* apkPath) {
std::string patchDevicePath = get_patch_path(apkPath);
return delete_device_file(patchDevicePath);
}
+#endif
static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy,
bool use_localagent) {
@@ -159,6 +163,7 @@
}
if (use_fastdeploy == true) {
+#if defined(ENABLE_FASTDEPLOY)
TemporaryFile metadataTmpFile;
std::string patchTmpFilePath;
{
@@ -179,6 +184,9 @@
adb_unlink(patchTmpFilePath.c_str());
delete_device_patch_file(file);
return 0;
+#else
+ error_exit("fastdeploy is disabled");
+#endif
} else {
struct stat sb;
if (stat(file, &sb) == -1) {
@@ -252,6 +260,7 @@
"/data/local/tmp/" + android::base::Basename(argv[last_apk]);
if (use_fastdeploy == true) {
+#if defined(ENABLE_FASTDEPLOY)
TemporaryFile metadataTmpFile;
TemporaryFile patchTmpFile;
@@ -261,6 +270,9 @@
create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
+#else
+ error_exit("fastdeploy is disabled");
+#endif
} else {
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
}
@@ -270,7 +282,9 @@
cleanup_apk:
if (use_fastdeploy == true) {
+#if defined(ENABLE_FASTDEPLOY)
delete_device_patch_file(apk_file[0]);
+#endif
}
delete_device_file(apk_dest);
return result;
@@ -334,12 +348,14 @@
error_exit("Attempting to use streaming install on unsupported device");
}
+#if defined(ENABLE_FASTDEPLOY)
if (use_fastdeploy == true && get_device_api_level() < kFastDeployMinApi) {
printf("Fast Deploy is only compatible with devices of API version %d or higher, "
"ignoring.\n",
kFastDeployMinApi);
use_fastdeploy = false;
}
+#endif
std::vector<const char*> passthrough_argv;
for (int i = 0; i < argc; i++) {
@@ -353,12 +369,16 @@
}
if (use_fastdeploy == true) {
+#if defined(ENABLE_FASTDEPLOY)
fastdeploy_set_local_agent(use_localagent);
update_agent(agent_update_strategy);
// The last argument must be the APK file
const char* file = passthrough_argv.back();
use_fastdeploy = find_package(file);
+#else
+ error_exit("fastdeploy is disabled");
+#endif
}
switch (installMode) {
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index 3c9dd04..b26c691 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -75,16 +75,20 @@
// Returns the device used to mount a directory in the fstab.
static std::string find_fstab_mount(const char* dir) {
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), dir);
- if (!rec) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
return "";
}
- if (fs_mgr_is_logical(rec)) {
- fs_mgr_update_logical_partition(rec);
+
+ auto entry = std::find_if(fstab.begin(), fstab.end(),
+ [&dir](const auto& entry) { return entry.mount_point == dir; });
+ if (entry == fstab.end()) {
+ return "";
}
- return rec->blk_device;
+ if (entry->fs_mgr_flags.logical) {
+ fs_mgr_update_logical_partition(&(*entry));
+ }
+ return entry->blk_device;
}
// The proc entry for / is full of lies, so check fstab instead.
diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp
index 3676de5..f5c28c6 100644
--- a/adb/daemon/set_verity_enable_state_service.cpp
+++ b/adb/daemon/set_verity_enable_state_service.cpp
@@ -41,8 +41,6 @@
#include "fec/io.h"
-struct fstab *fstab;
-
#ifdef ALLOW_ADBD_DISABLE_VERITY
static const bool kAllowDisableVerity = true;
#else
@@ -213,18 +211,18 @@
// Not using AVB - assume VB1.0.
// read all fstab entries at once from all sources
- if (!fstab) fstab = fs_mgr_read_fstab_default();
- if (!fstab) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
WriteFdExactly(fd.get(), "Failed to read fstab\n");
suggest_run_adb_root(fd.get());
return;
}
// Loop through entries looking for ones that verity manages.
- for (int i = 0; i < fstab->num_entries; i++) {
- if (fs_mgr_is_verified(&fstab->recs[i])) {
- if (set_verity_enabled_state(fd.get(), fstab->recs[i].blk_device,
- fstab->recs[i].mount_point, enable)) {
+ for (const auto& entry : fstab) {
+ if (entry.fs_mgr_flags.verify) {
+ if (set_verity_enabled_state(fd.get(), entry.blk_device.c_str(),
+ entry.mount_point.c_str(), enable)) {
any_changed = true;
}
}
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 5b4c51e..f7c39f0 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -359,8 +359,9 @@
return nullptr;
}
+ int fd_value = fd.get();
asocket* s = create_local_socket(std::move(fd));
- LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd.get();
+ LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd_value;
#if !ADB_HOST
if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index e433787..46d4bd3 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -34,25 +34,27 @@
#include <stdlib.h>
#include <string.h>
-void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline) {
+void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline) {
if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
}
-boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
- const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src,
- std::vector<char>* out) {
+boot_img_hdr_v2* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
+ const std::vector<char>& second, const std::vector<char>& dtb,
+ size_t base, const boot_img_hdr_v2& src, std::vector<char>* out) {
const size_t page_mask = src.page_size - 1;
int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask);
int64_t kernel_actual = (kernel.size() + page_mask) & (~page_mask);
int64_t ramdisk_actual = (ramdisk.size() + page_mask) & (~page_mask);
int64_t second_actual = (second.size() + page_mask) & (~page_mask);
+ int64_t dtb_actual = (dtb.size() + page_mask) & (~page_mask);
- int64_t bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual;
+ int64_t bootimg_size =
+ header_actual + kernel_actual + ramdisk_actual + second_actual + dtb_actual;
out->resize(bootimg_size);
- boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(out->data());
+ boot_img_hdr_v2* hdr = reinterpret_cast<boot_img_hdr_v2*>(out->data());
*hdr = src;
memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
@@ -66,13 +68,19 @@
hdr->second_addr += base;
hdr->tags_addr += base;
- if (hdr->header_version != 0) {
+ if (hdr->header_version == 1) {
hdr->header_size = sizeof(boot_img_hdr_v1);
+ } else if (hdr->header_version == 2) {
+ hdr->header_size = sizeof(boot_img_hdr_v2);
+ hdr->dtb_size = dtb.size();
+ hdr->dtb_addr += base;
}
memcpy(hdr->magic + hdr->page_size, kernel.data(), kernel.size());
memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk.data(), ramdisk.size());
memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second.data(),
second.size());
+ memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual + second_actual, dtb.data(),
+ dtb.size());
return hdr;
}
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
index a4e8870..b7cf9bd 100644
--- a/fastboot/bootimg_utils.h
+++ b/fastboot/bootimg_utils.h
@@ -35,7 +35,7 @@
#include <string>
#include <vector>
-boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
- const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src,
- std::vector<char>* out);
-void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline);
+boot_img_hdr_v2* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
+ const std::vector<char>& second, const std::vector<char>& dtb,
+ size_t base, const boot_img_hdr_v2& src, std::vector<char>* out);
+void bootimg_set_cmdline(boot_img_hdr_v2* h, const std::string& cmdline);
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index f737405..99854c9 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -52,15 +52,17 @@
// Following appears to have a first time 2% impact on flashing speeds.
// Convert partition_name to a validated mount point and wipe.
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto mount_point = fstab->recs[i].mount_point;
- if (!mount_point) continue;
- auto partition = android::base::Basename(mount_point);
- if ("/"s == mount_point) partition = "system";
+ Fstab fstab;
+ ReadDefaultFstab(&fstab);
+
+ for (const auto& entry : fstab) {
+ auto partition = android::base::Basename(entry.mount_point);
+ if ("/" == entry.mount_point) {
+ partition = "system";
+ }
+
if ((partition + device->GetCurrentSlot()) == partition_name) {
- fs_mgr_overlayfs_teardown(mount_point);
+ fs_mgr_overlayfs_teardown(entry.mount_point.c_str());
}
}
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index d753f0f..17cab3a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -92,8 +92,9 @@
static int64_t target_sparse_limit = -1;
static unsigned g_base_addr = 0x10000000;
-static boot_img_hdr_v1 g_boot_img_hdr = {};
+static boot_img_hdr_v2 g_boot_img_hdr = {};
static std::string g_cmdline;
+static std::string g_dtb_path;
static bool g_disable_verity = false;
static bool g_disable_verification = false;
@@ -394,11 +395,13 @@
" Download and boot kernel from RAM.\n"
" flash:raw PARTITION KERNEL [RAMDISK [SECOND]]\n"
" Create boot image and flash it.\n"
+ " --dtb DTB Specify path to DTB for boot image header version 2.\n"
" --cmdline CMDLINE Override kernel command line.\n"
" --base ADDRESS Set kernel base address (default: 0x10000000).\n"
" --kernel-offset Set kernel offset (default: 0x00008000).\n"
" --ramdisk-offset Set ramdisk offset (default: 0x01000000).\n"
" --tags-offset Set tags offset (default: 0x00000100).\n"
+ " --dtb-offset Set dtb offset (default: 0x01100000).\n"
" --page-size BYTES Set flash page size (default: 2048).\n"
" --header-version VERSION Set boot image header version.\n"
" --os-version MAJOR[.MINOR[.PATCH]]\n"
@@ -448,12 +451,12 @@
}
// Is this actually a boot image?
- if (kernel_data.size() < sizeof(boot_img_hdr_v1)) {
+ if (kernel_data.size() < sizeof(boot_img_hdr_v2)) {
die("cannot load '%s': too short", kernel.c_str());
}
if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
if (!g_cmdline.empty()) {
- bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kernel_data.data()), g_cmdline);
+ bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v2*>(kernel_data.data()), g_cmdline);
}
if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk");
@@ -474,15 +477,26 @@
die("cannot load '%s': %s", second_stage.c_str(), strerror(errno));
}
}
+
+ 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);
+ }
+ 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");
std::vector<char> out;
- boot_img_hdr_v1* boot_image_data = mkbootimg(kernel_data, ramdisk_data, second_stage_data,
- g_base_addr, g_boot_img_hdr, &out);
+ boot_img_hdr_v2* boot_image_data = mkbootimg(kernel_data, ramdisk_data, second_stage_data,
+ dtb_data, g_base_addr, g_boot_img_hdr, &out);
if (!g_cmdline.empty()) bootimg_set_cmdline(boot_image_data, g_cmdline);
fprintf(stderr, "creating boot image - %zu bytes\n", out.size());
-
return out;
}
@@ -1586,6 +1600,7 @@
g_boot_img_hdr.second_addr = 0x00f00000;
g_boot_img_hdr.tags_addr = 0x00000100;
g_boot_img_hdr.page_size = 2048;
+ g_boot_img_hdr.dtb_addr = 0x01100000;
const struct option longopts[] = {
{"base", required_argument, 0, 0},
@@ -1605,6 +1620,8 @@
{"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},
@@ -1632,6 +1649,8 @@
force_flash = true;
} else if (name == "header-version") {
g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
+ } else if (name == "dtb") {
+ g_dtb_path = optarg;
} else if (name == "kernel-offset") {
g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16);
} else if (name == "os-patch-level") {
@@ -1649,6 +1668,8 @@
skip_secondary = true;
} else if (name == "slot") {
slot_override = optarg;
+ } else if (name == "dtb-offset") {
+ g_boot_img_hdr.dtb_addr = strtoul(optarg, 0, 16);
} else if (name == "tags-offset") {
g_boot_img_hdr.tags_addr = strtoul(optarg, 0, 16);
} else if (name == "unbuffered") {
@@ -1828,7 +1849,6 @@
if (!args.empty()) ramdisk = next_arg(&args);
std::string second_stage;
if (!args.empty()) second_stage = next_arg(&args);
-
auto data = LoadBootableImage(kernel, ramdisk, second_stage);
fb->Download("boot.img", data);
fb->Boot();
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ded3678..943a071 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -889,19 +889,6 @@
return true;
}
-bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
- auto entry = FstabRecToFstabEntry(rec);
-
- if (!fs_mgr_update_logical_partition(&entry)) {
- return false;
- }
-
- free(rec->blk_device);
- rec->blk_device = strdup(entry.blk_device.c_str());
-
- return true;
-}
-
class CheckpointManager {
public:
CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
@@ -1011,9 +998,7 @@
if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
return false;
}
- auto it = std::find_if(fstab.begin(), fstab.end(),
- [&](const auto& entry) { return entry.mount_point == mount_point; });
- return it != fstab.end();
+ return GetEntryForMountPoint(&fstab, mount_point) != nullptr;
}
// When multiple fstab records share the same mount_point, it will try to mount each
@@ -1103,6 +1088,13 @@
// Skips mounting the device.
continue;
}
+ } else if (!current_entry.avb_key.empty()) {
+ if (AvbHandle::SetUpStandaloneAvbHashtree(¤t_entry) == AvbHashtreeResult::kFail) {
+ LERROR << "Failed to set up AVB on standalone partition: "
+ << current_entry.mount_point << ", skipping!";
+ // Skips mounting the device.
+ continue;
+ }
} else if ((current_entry.fs_mgr_flags.verify)) {
int rc = fs_mgr_setup_verity(¤t_entry, true);
if (__android_log_is_debuggable() &&
@@ -1339,6 +1331,13 @@
// Skips mounting the device.
continue;
}
+ } else if (!fstab_entry.avb_key.empty()) {
+ if (AvbHandle::SetUpStandaloneAvbHashtree(&fstab_entry) == AvbHashtreeResult::kFail) {
+ LERROR << "Failed to set up AVB on standalone partition: "
+ << fstab_entry.mount_point << ", skipping!";
+ // Skips mounting the device.
+ continue;
+ }
} else if (fstab_entry.fs_mgr_flags.verify) {
int rc = fs_mgr_setup_verity(&fstab_entry, true);
if (__android_log_is_debuggable() &&
@@ -1397,6 +1396,15 @@
needs_checkpoint);
}
+int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
+}
+
+int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
+ bool needs_checkpoint) {
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
+}
+
/*
* mount a tmpfs filesystem at the given point.
* return 0 on success, non-zero on failure.
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index aeab893..146e82f 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <algorithm>
+#include <array>
#include <utility>
#include <vector>
@@ -35,146 +36,37 @@
#include "fs_mgr_priv.h"
+using android::base::ParseByteCount;
+using android::base::ParseInt;
using android::base::Split;
using android::base::StartsWith;
const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
-struct fs_mgr_flag_values {
- std::string key_loc;
- std::string key_dir;
- std::string verity_loc;
- std::string sysfs_path;
- std::string zram_loopback_path;
- uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default
- std::string zram_backing_dev_path;
- off64_t part_length = 0;
- std::string label;
- int partnum = -1;
- int swap_prio = -1;
- int max_comp_streams = 0;
- off64_t zram_size = 0;
- off64_t reserved_size = 0;
- int file_contents_mode = 0;
- int file_names_mode = 0;
- off64_t erase_blk_size = 0;
- off64_t logical_blk_size = 0;
- std::string vbmeta_partition;
-};
-
struct flag_list {
const char *name;
uint64_t flag;
};
-static struct flag_list mount_flags[] = {
- { "noatime", MS_NOATIME },
- { "noexec", MS_NOEXEC },
- { "nosuid", MS_NOSUID },
- { "nodev", MS_NODEV },
- { "nodiratime", MS_NODIRATIME },
- { "ro", MS_RDONLY },
- { "rw", 0 },
- { "remount", MS_REMOUNT },
- { "bind", MS_BIND },
- { "rec", MS_REC },
- { "unbindable", MS_UNBINDABLE },
- { "private", MS_PRIVATE },
- { "slave", MS_SLAVE },
- { "shared", MS_SHARED },
- { "defaults", 0 },
- { 0, 0 },
-};
-
-static struct flag_list fs_mgr_flags[] = {
- {"wait", MF_WAIT},
- {"check", MF_CHECK},
- {"encryptable=", MF_CRYPT},
- {"forceencrypt=", MF_FORCECRYPT},
- {"fileencryption=", MF_FILEENCRYPTION},
- {"forcefdeorfbe=", MF_FORCEFDEORFBE},
- {"keydirectory=", MF_KEYDIRECTORY},
- {"nonremovable", MF_NONREMOVABLE},
- {"voldmanaged=", MF_VOLDMANAGED},
- {"length=", MF_LENGTH},
- {"recoveryonly", MF_RECOVERYONLY},
- {"swapprio=", MF_SWAPPRIO},
- {"zramsize=", MF_ZRAMSIZE},
- {"max_comp_streams=", MF_MAX_COMP_STREAMS},
- {"verifyatboot", MF_VERIFYATBOOT},
- {"verify", MF_VERIFY},
- {"avb", MF_AVB},
- {"avb=", MF_AVB},
- {"noemulatedsd", MF_NOEMULATEDSD},
- {"notrim", MF_NOTRIM},
- {"formattable", MF_FORMATTABLE},
- {"slotselect", MF_SLOTSELECT},
- {"nofail", MF_NOFAIL},
- {"first_stage_mount", MF_FIRST_STAGE_MOUNT},
- {"latemount", MF_LATEMOUNT},
- {"reservedsize=", MF_RESERVEDSIZE},
- {"quota", MF_QUOTA},
- {"eraseblk=", MF_ERASEBLKSIZE},
- {"logicalblk=", MF_LOGICALBLKSIZE},
- {"sysfs_path=", MF_SYSFS},
+static struct flag_list mount_flags_list[] = {
+ {"noatime", MS_NOATIME},
+ {"noexec", MS_NOEXEC},
+ {"nosuid", MS_NOSUID},
+ {"nodev", MS_NODEV},
+ {"nodiratime", MS_NODIRATIME},
+ {"ro", MS_RDONLY},
+ {"rw", 0},
+ {"remount", MS_REMOUNT},
+ {"bind", MS_BIND},
+ {"rec", MS_REC},
+ {"unbindable", MS_UNBINDABLE},
+ {"private", MS_PRIVATE},
+ {"slave", MS_SLAVE},
+ {"shared", MS_SHARED},
{"defaults", 0},
- {"logical", MF_LOGICAL},
- {"checkpoint=block", MF_CHECKPOINT_BLK},
- {"checkpoint=fs", MF_CHECKPOINT_FS},
- {"slotselect_other", MF_SLOTSELECT_OTHER},
- {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
- {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
- {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
- {"fsverity", MF_FS_VERITY},
- {0, 0},
};
-#define EM_AES_256_XTS 1
-#define EM_ICE 2
-#define EM_AES_256_CTS 3
-#define EM_AES_256_HEH 4
-#define EM_ADIANTUM 5
-
-static const struct flag_list file_contents_encryption_modes[] = {
- {"aes-256-xts", EM_AES_256_XTS},
- {"adiantum", EM_ADIANTUM},
- {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
- {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
- {0, 0},
-};
-
-static const struct flag_list file_names_encryption_modes[] = {
- {"aes-256-cts", EM_AES_256_CTS},
- {"aes-256-heh", EM_AES_256_HEH},
- {"adiantum", EM_ADIANTUM},
- {0, 0},
-};
-
-static int encryption_mode_to_flag(const struct flag_list* list, const char* mode,
- const char* type) {
- const struct flag_list *j;
-
- for (j = list; j->name; ++j) {
- if (!strcmp(mode, j->name)) {
- return j->flag;
- }
- }
- LERROR << "Unknown " << type << " encryption mode: " << mode;
- return 0;
-}
-
-static const char* flag_to_encryption_mode(const struct flag_list* list, uint64_t flag) {
- const struct flag_list *j;
-
- for (j = list; j->name; ++j) {
- if (flag == j->flag) {
- return j->name;
- }
- }
- return nullptr;
-}
-
-static off64_t calculate_zram_size(unsigned int percentage) {
+static off64_t calculate_zram_size(int percentage) {
off64_t total;
total = sysconf(_SC_PHYS_PAGES);
@@ -186,19 +78,6 @@
return total;
}
-static off64_t parse_size(const char* arg) {
- char *endptr;
- off64_t size = strtoll(arg, &endptr, 10);
- if (*endptr == 'k' || *endptr == 'K')
- size *= 1024LL;
- else if (*endptr == 'm' || *endptr == 'M')
- size *= 1024LL * 1024LL;
- else if (*endptr == 'g' || *endptr == 'G')
- size *= 1024LL * 1024LL * 1024LL;
-
- return size;
-}
-
/* fills 'dt_value' with the underlying device tree value string without
* the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
* otherwise.
@@ -217,174 +96,254 @@
return false;
}
-static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals,
- std::string* fs_options) {
- uint64_t f = 0;
- int i;
- char *p;
- char *savep;
+const static std::array<const char*, 3> kFileContentsEncryptionMode = {
+ "aes-256-xts",
+ "adiantum",
+ "ice",
+};
- p = strtok_r(flags, ",", &savep);
- while (p) {
- /* Look for the flag "p" in the flag list "fl"
- * If not found, the loop exits with fl[i].name being null.
- */
- for (i = 0; fl[i].name; i++) {
- auto name = fl[i].name;
- auto len = strlen(name);
- auto end = len;
- if (name[end - 1] == '=') --end;
- if (!strncmp(p, name, len) && (p[end] == name[end])) {
- f |= fl[i].flag;
- if (!flag_vals) break;
- if (p[end] != '=') break;
- char* arg = p + end + 1;
- auto flag = fl[i].flag;
- if (flag == MF_CRYPT) {
- /* The encryptable flag is followed by an = and the
- * location of the keys. Get it and return it.
- */
- flag_vals->key_loc = arg;
- } else if (flag == MF_VERIFY) {
- /* If the verify flag is followed by an = and the
- * location for the verity state, get it and return it.
- */
- flag_vals->verity_loc = arg;
- } else if (flag == MF_FORCECRYPT) {
- /* The forceencrypt flag is followed by an = and the
- * location of the keys. Get it and return it.
- */
- flag_vals->key_loc = arg;
- } else if (flag == MF_FORCEFDEORFBE) {
- /* The forcefdeorfbe flag is followed by an = and the
- * location of the keys. Get it and return it.
- */
- flag_vals->key_loc = arg;
- flag_vals->file_contents_mode = EM_AES_256_XTS;
- flag_vals->file_names_mode = EM_AES_256_CTS;
- } else if (flag == MF_FILEENCRYPTION) {
- /* The fileencryption flag is followed by an = and
- * the mode of contents encryption, then optionally a
- * : and the mode of filenames encryption (defaults
- * to aes-256-cts). Get it and return it.
- */
- auto mode = arg;
- auto colon = strchr(mode, ':');
- if (colon) {
- *colon = '\0';
- }
- flag_vals->file_contents_mode =
- encryption_mode_to_flag(file_contents_encryption_modes,
- mode, "file contents");
- if (colon) {
- flag_vals->file_names_mode =
- encryption_mode_to_flag(file_names_encryption_modes,
- colon + 1, "file names");
- } else if (flag_vals->file_contents_mode == EM_ADIANTUM) {
- flag_vals->file_names_mode = EM_ADIANTUM;
- } else {
- flag_vals->file_names_mode = EM_AES_256_CTS;
- }
- } else if (flag == MF_KEYDIRECTORY) {
- /* The metadata flag is followed by an = and the
- * directory for the keys. Get it and return it.
- */
- flag_vals->key_dir = arg;
- } else if (flag == MF_LENGTH) {
- /* The length flag is followed by an = and the
- * size of the partition. Get it and return it.
- */
- flag_vals->part_length = strtoll(arg, NULL, 0);
- } else if (flag == MF_VOLDMANAGED) {
- /* The voldmanaged flag is followed by an = and the
- * label, a colon and the partition number or the
- * word "auto", e.g.
- * voldmanaged=sdcard:3
- * Get and return them.
- */
- auto label_start = arg;
- auto label_end = strchr(label_start, ':');
+const static std::array<const char*, 3> kFileNamesEncryptionMode = {
+ "aes-256-cts",
+ "aes-256-heh",
+ "adiantum",
+};
- if (label_end) {
- flag_vals->label = std::string(label_start, (int)(label_end - label_start));
- auto part_start = label_end + 1;
- if (!strcmp(part_start, "auto")) {
- flag_vals->partnum = -1;
- } else {
- flag_vals->partnum = strtol(part_start, NULL, 0);
- }
- } else {
- LERROR << "Warning: voldmanaged= flag malformed";
- }
- } else if (flag == MF_SWAPPRIO) {
- flag_vals->swap_prio = strtoll(arg, NULL, 0);
- } else if (flag == MF_MAX_COMP_STREAMS) {
- flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
- } else if (flag == MF_AVB) {
- flag_vals->vbmeta_partition = arg;
- } else if (flag == MF_ZRAMSIZE) {
- auto is_percent = !!strrchr(arg, '%');
- auto val = strtoll(arg, NULL, 0);
- if (is_percent)
- flag_vals->zram_size = calculate_zram_size(val);
- else
- flag_vals->zram_size = val;
- } else if (flag == MF_RESERVEDSIZE) {
- /* The reserved flag is followed by an = and the
- * reserved size of the partition. Get it and return it.
- */
- flag_vals->reserved_size = parse_size(arg);
- } else if (flag == MF_ERASEBLKSIZE) {
- /* The erase block size flag is followed by an = and the flash
- * erase block size. Get it, check that it is a power of 2 and
- * at least 4096, and return it.
- */
- auto val = strtoll(arg, nullptr, 0);
- if (val >= 4096 && (val & (val - 1)) == 0)
- flag_vals->erase_blk_size = val;
- } else if (flag == MF_LOGICALBLKSIZE) {
- /* The logical block size flag is followed by an = and the flash
- * logical block size. Get it, check that it is a power of 2 and
- * at least 4096, and return it.
- */
- auto val = strtoll(arg, nullptr, 0);
- if (val >= 4096 && (val & (val - 1)) == 0)
- flag_vals->logical_blk_size = val;
- } else if (flag == MF_SYSFS) {
- /* The path to trigger device gc by idle-maint of vold. */
- flag_vals->sysfs_path = arg;
- } else if (flag == MF_ZRAM_LOOPBACK_PATH) {
- /* The path to use loopback for zram. */
- flag_vals->zram_loopback_path = arg;
- } else if (flag == MF_ZRAM_LOOPBACK_SIZE) {
- if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) {
- LERROR << "Warning: zram_loopback_size = flag malformed";
- }
- } else if (flag == MF_ZRAM_BACKING_DEV_PATH) {
- /* The path to use loopback for zram. */
- flag_vals->zram_backing_dev_path = arg;
- }
- break;
- }
- }
+static void ParseFileEncryption(const std::string& arg, FstabEntry* entry) {
+ // The fileencryption flag is followed by an = and the mode of contents encryption, then
+ // optionally a and the mode of filenames encryption (defaults to aes-256-cts). Get it and
+ // return it.
+ entry->fs_mgr_flags.file_encryption = true;
- if (!fl[i].name) {
- if (fs_options) {
- // It's not a known flag, so it must be a filesystem specific
- // option. Add it to fs_options if it was passed in.
- if (!fs_options->empty()) {
- fs_options->append(","); // appends a comma if not the first
- }
- fs_options->append(p);
- } else {
- // fs_options was not passed in, so if the flag is unknown it's an error.
- LERROR << "Warning: unknown flag " << p;
- }
- }
- p = strtok_r(NULL, ",", &savep);
+ auto parts = Split(arg, ":");
+ if (parts.empty() || parts.size() > 2) {
+ LWARNING << "Warning: fileencryption= flag malformed: " << arg;
+ return;
}
- return f;
+ // Alias for backwards compatibility.
+ if (parts[0] == "software") {
+ parts[0] = "aes-256-xts";
+ }
+
+ if (std::find(kFileContentsEncryptionMode.begin(), kFileContentsEncryptionMode.end(),
+ parts[0]) == kFileContentsEncryptionMode.end()) {
+ LWARNING << "fileencryption= flag malformed, file contents encryption mode not found: "
+ << arg;
+ return;
+ }
+
+ entry->file_contents_mode = parts[0];
+
+ if (parts.size() == 2) {
+ if (std::find(kFileNamesEncryptionMode.begin(), kFileNamesEncryptionMode.end(), parts[1]) ==
+ kFileNamesEncryptionMode.end()) {
+ LWARNING << "fileencryption= flag malformed, file names encryption mode not found: "
+ << arg;
+ return;
+ }
+
+ entry->file_names_mode = parts[1];
+ } else if (entry->file_contents_mode == "adiantum") {
+ entry->file_names_mode = "adiantum";
+ } else {
+ entry->file_names_mode = "aes-256-cts";
+ }
+}
+
+static bool SetMountFlag(const std::string& flag, FstabEntry* entry) {
+ for (const auto& [name, value] : mount_flags_list) {
+ if (flag == name) {
+ entry->flags |= value;
+ return true;
+ }
+ }
+ return false;
+}
+
+static void ParseMountFlags(const std::string& flags, FstabEntry* entry) {
+ std::string fs_options;
+ for (const auto& flag : Split(flags, ",")) {
+ if (!SetMountFlag(flag, entry)) {
+ // Unknown flag, so it must be a filesystem specific option.
+ if (!fs_options.empty()) {
+ fs_options.append(","); // appends a comma if not the first
+ }
+ fs_options.append(flag);
+ }
+ }
+ entry->fs_options = std::move(fs_options);
+}
+
+static void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
+ entry->fs_mgr_flags.val = 0U;
+ for (const auto& flag : Split(flags, ",")) {
+ std::string arg;
+ if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
+ arg = flag.substr(equal_sign + 1);
+ }
+
+ // First handle flags that simply set a boolean.
+#define CheckFlag(flag_name, value) \
+ if (flag == flag_name) { \
+ entry->fs_mgr_flags.value = true; \
+ continue; \
+ }
+
+ CheckFlag("wait", wait);
+ CheckFlag("check", check);
+ CheckFlag("nonremovable", nonremovable);
+ CheckFlag("recoveryonly", recovery_only);
+ CheckFlag("noemulatedsd", no_emulated_sd);
+ CheckFlag("notrim", no_trim);
+ CheckFlag("verify", verify);
+ CheckFlag("formattable", formattable);
+ CheckFlag("slotselect", slot_select);
+ CheckFlag("latemount", late_mount);
+ CheckFlag("nofail", no_fail);
+ CheckFlag("verifyatboot", verify_at_boot);
+ CheckFlag("quota", quota);
+ CheckFlag("avb", avb);
+ CheckFlag("logical", logical);
+ CheckFlag("checkpoint=block", checkpoint_blk);
+ CheckFlag("checkpoint=fs", checkpoint_fs);
+ CheckFlag("first_stage_mount", first_stage_mount);
+ CheckFlag("slotselect_other", slot_select_other);
+ CheckFlag("fsverity", fs_verity);
+
+#undef CheckFlag
+
+ // Then handle flags that take an argument.
+ if (StartsWith(flag, "encryptable=")) {
+ // The encryptable flag is followed by an = and the location of the keys.
+ entry->fs_mgr_flags.crypt = true;
+ entry->key_loc = arg;
+ } else if (StartsWith(flag, "voldmanaged=")) {
+ // The voldmanaged flag is followed by an = and the label, a colon and the partition
+ // number or the word "auto", e.g. voldmanaged=sdcard:3
+ entry->fs_mgr_flags.vold_managed = true;
+ auto parts = Split(arg, ":");
+ if (parts.size() != 2) {
+ LWARNING << "Warning: voldmanaged= flag malformed: " << arg;
+ continue;
+ }
+
+ entry->label = std::move(parts[0]);
+ if (parts[1] == "auto") {
+ entry->partnum = -1;
+ } else {
+ if (!ParseInt(parts[1], &entry->partnum)) {
+ entry->partnum = -1;
+ LWARNING << "Warning: voldmanaged= flag malformed: " << arg;
+ continue;
+ }
+ }
+ } else if (StartsWith(flag, "length=")) {
+ // The length flag is followed by an = and the size of the partition.
+ entry->fs_mgr_flags.length = true;
+ if (!ParseInt(arg, &entry->length)) {
+ LWARNING << "Warning: length= flag malformed: " << arg;
+ }
+ } else if (StartsWith(flag, "swapprio=")) {
+ entry->fs_mgr_flags.swap_prio = true;
+ if (!ParseInt(arg, &entry->swap_prio)) {
+ LWARNING << "Warning: length= flag malformed: " << arg;
+ }
+ } else if (StartsWith(flag, "zramsize=")) {
+ entry->fs_mgr_flags.zram_size = true;
+
+ if (!arg.empty() && arg.back() == '%') {
+ arg.pop_back();
+ int val;
+ if (ParseInt(arg, &val, 0, 100)) {
+ entry->zram_size = calculate_zram_size(val);
+ } else {
+ LWARNING << "Warning: zramsize= flag malformed: " << arg;
+ }
+ } else {
+ if (!ParseInt(arg, &entry->zram_size)) {
+ LWARNING << "Warning: zramsize= flag malformed: " << arg;
+ }
+ }
+ } else if (StartsWith(flag, "verify=")) {
+ // If the verify flag is followed by an = and the location for the verity state.
+ entry->fs_mgr_flags.verify = true;
+ entry->verity_loc = arg;
+ } else if (StartsWith(flag, "forceencrypt=")) {
+ // The forceencrypt flag is followed by an = and the location of the keys.
+ entry->fs_mgr_flags.force_crypt = true;
+ entry->key_loc = arg;
+ } else if (StartsWith(flag, "fileencryption=")) {
+ ParseFileEncryption(arg, entry);
+ } else if (StartsWith(flag, "forcefdeorfbe=")) {
+ // The forcefdeorfbe flag is followed by an = and the location of the keys. Get it and
+ // return it.
+ entry->fs_mgr_flags.force_fde_or_fbe = true;
+ entry->key_loc = arg;
+ entry->file_contents_mode = "aes-256-xts";
+ entry->file_names_mode = "aes-256-cts";
+ } else if (StartsWith(flag, "max_comp_streams=")) {
+ entry->fs_mgr_flags.max_comp_streams = true;
+ if (!ParseInt(arg, &entry->max_comp_streams)) {
+ LWARNING << "Warning: max_comp_streams= flag malformed: " << arg;
+ }
+ } else if (StartsWith(flag, "reservedsize=")) {
+ // The reserved flag is followed by an = and the reserved size of the partition.
+ entry->fs_mgr_flags.reserved_size = true;
+ uint64_t size;
+ if (!ParseByteCount(arg, &size)) {
+ LWARNING << "Warning: reservedsize= flag malformed: " << arg;
+ } else {
+ entry->reserved_size = static_cast<off64_t>(size);
+ }
+ } else if (StartsWith(flag, "eraseblk=")) {
+ // The erase block size flag is followed by an = and the flash erase block size. Get it,
+ // check that it is a power of 2 and at least 4096, and return it.
+ entry->fs_mgr_flags.erase_blk_size = true;
+ off64_t val;
+ if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
+ LWARNING << "Warning: eraseblk= flag malformed: " << arg;
+ } else {
+ entry->erase_blk_size = val;
+ }
+ } else if (StartsWith(flag, "logicalblk=")) {
+ // The logical block size flag is followed by an = and the flash logical block size. Get
+ // it, check that it is a power of 2 and at least 4096, and return it.
+ entry->fs_mgr_flags.logical_blk_size = true;
+ off64_t val;
+ if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
+ LWARNING << "Warning: logicalblk= flag malformed: " << arg;
+ } else {
+ entry->logical_blk_size = val;
+ }
+ } else if (StartsWith(flag, "avb")) {
+ entry->fs_mgr_flags.avb = true;
+ entry->vbmeta_partition = arg;
+ } else if (StartsWith(flag, "keydirectory=")) {
+ // The metadata flag is followed by an = and the directory for the keys.
+ entry->fs_mgr_flags.key_directory = true;
+ entry->key_dir = arg;
+ } else if (StartsWith(flag, "sysfs_path=")) {
+ // The path to trigger device gc by idle-maint of vold.
+ entry->fs_mgr_flags.sysfs = true;
+ entry->sysfs_path = arg;
+ } else if (StartsWith(flag, "zram_loopback_path=")) {
+ // The path to use loopback for zram.
+ entry->fs_mgr_flags.zram_loopback_path = true;
+ entry->zram_loopback_path = arg;
+ } else if (StartsWith(flag, "zram_loopback_size=")) {
+ entry->fs_mgr_flags.zram_loopback_size = true;
+ if (!ParseByteCount(arg, &entry->zram_loopback_size)) {
+ LWARNING << "Warning: zram_loopback_size= flag malformed: " << arg;
+ }
+ } else if (StartsWith(flag, "zram_backing_dev_path=")) {
+ entry->fs_mgr_flags.zram_backing_dev_path = true;
+ entry->zram_backing_dev_path = arg;
+ } else if (StartsWith(flag, "avb_key=")) {
+ entry->avb_key = arg;
+ } else {
+ LWARNING << "Warning: unknown flag: " << flag;
+ }
+ }
}
static std::string init_android_dt_dir() {
@@ -520,7 +479,6 @@
const char *delim = " \t";
char *save_ptr, *p;
Fstab fstab;
- struct fs_mgr_flag_values flag_vals;
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
/* if the last character is a newline, shorten the string by 1 byte */
@@ -561,7 +519,8 @@
LERROR << "Error parsing mount_flags";
goto err;
}
- entry.flags = parse_flags(p, mount_flags, nullptr, &entry.fs_options);
+
+ ParseMountFlags(p, &entry);
// For /proc/mounts, ignore everything after mnt_freq and mnt_passno
if (proc_mounts) {
@@ -570,27 +529,9 @@
LERROR << "Error parsing fs_mgr_options";
goto err;
}
- entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, nullptr);
- entry.key_loc = std::move(flag_vals.key_loc);
- entry.key_dir = std::move(flag_vals.key_dir);
- entry.verity_loc = std::move(flag_vals.verity_loc);
- entry.length = flag_vals.part_length;
- entry.label = std::move(flag_vals.label);
- entry.partnum = flag_vals.partnum;
- entry.swap_prio = flag_vals.swap_prio;
- entry.max_comp_streams = flag_vals.max_comp_streams;
- entry.zram_size = flag_vals.zram_size;
- entry.reserved_size = flag_vals.reserved_size;
- entry.file_contents_mode = flag_vals.file_contents_mode;
- entry.file_names_mode = flag_vals.file_names_mode;
- entry.erase_blk_size = flag_vals.erase_blk_size;
- entry.logical_blk_size = flag_vals.logical_blk_size;
- entry.sysfs_path = std::move(flag_vals.sysfs_path);
- entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition);
- entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path);
- entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size);
- entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path);
+ ParseFsMgrFlags(p, &entry);
+
if (entry.fs_mgr_flags.logical) {
entry.logical_partition_name = entry.blk_device;
}
@@ -834,6 +775,8 @@
free(fstab->recs[i].key_loc);
free(fstab->recs[i].key_dir);
free(fstab->recs[i].label);
+ free(fstab->recs[i].file_contents_mode);
+ free(fstab->recs[i].file_names_mode);
free(fstab->recs[i].sysfs_path);
free(fstab->recs[i].zram_loopback_path);
free(fstab->recs[i].zram_backing_dev_path);
@@ -846,39 +789,8 @@
free(fstab);
}
-/* Add an entry to the fstab, and return 0 on success or -1 on error */
-int fs_mgr_add_entry(struct fstab *fstab,
- const char *mount_point, const char *fs_type,
- const char *blk_device)
-{
- struct fstab_rec *new_fstab_recs;
- int n = fstab->num_entries;
-
- new_fstab_recs = (struct fstab_rec *)
- realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
-
- if (!new_fstab_recs) {
- return -1;
- }
-
- /* A new entry was added, so initialize it */
- memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
- new_fstab_recs[n].mount_point = strdup(mount_point);
- new_fstab_recs[n].fs_type = strdup(fs_type);
- new_fstab_recs[n].blk_device = strdup(blk_device);
- new_fstab_recs[n].length = 0;
-
- /* Update the fstab struct */
- fstab->recs = new_fstab_recs;
- fstab->num_entries++;
-
- return 0;
-}
-
-/*
- * Returns the fstab_rec* whose mount_point is path.
- * Returns nullptr if not found.
- */
+// Returns the fstab_rec* whose mount_point is path.
+// Returns nullptr if not found.
struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
if (!fstab) {
return nullptr;
@@ -891,6 +803,20 @@
return nullptr;
}
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path) {
+ if (fstab == nullptr) {
+ return nullptr;
+ }
+
+ for (auto& entry : *fstab) {
+ if (entry.mount_point == path) {
+ return &entry;
+ }
+ }
+
+ return nullptr;
+}
+
std::set<std::string> fs_mgr_get_boot_devices() {
// First check the kernel commandline, then try the device tree otherwise
std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
@@ -975,8 +901,8 @@
legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
- legacy_fstab->recs[i].file_contents_mode = fstab[i].file_contents_mode;
- legacy_fstab->recs[i].file_names_mode = fstab[i].file_names_mode;
+ legacy_fstab->recs[i].file_contents_mode = strdup(fstab[i].file_contents_mode.c_str());
+ legacy_fstab->recs[i].file_names_mode = strdup(fstab[i].file_names_mode.c_str());
legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
@@ -1002,34 +928,15 @@
return fstab->fs_mgr_flags & MF_VERIFY;
}
-int fs_mgr_is_avb(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_AVB;
-}
-
-int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
-}
-
int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
}
-int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
-}
-
-void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
- const char **contents_mode_ret,
- const char **filenames_mode_ret)
-{
- *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes,
- fstab->file_contents_mode);
- *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes,
- fstab->file_names_mode);
+void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
+ const char** filenames_mode_ret) {
+ *contents_mode_ret = fstab->file_contents_mode;
+ *filenames_mode_ret = fstab->file_names_mode;
}
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
@@ -1046,26 +953,6 @@
return fstab->fs_mgr_flags & MF_NOTRIM;
}
-int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & (MF_FORMATTABLE);
-}
-
-int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_SLOTSELECT;
-}
-
-int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_NOFAIL;
-}
-
-int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_FIRST_STAGE_MOUNT;
-}
-
-int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_LATEMOUNT;
-}
-
int fs_mgr_is_quota(const struct fstab_rec* fstab) {
return fstab->fs_mgr_flags & MF_QUOTA;
}
@@ -1091,10 +978,6 @@
return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
}
-int fs_mgr_is_fs_verity(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_FS_VERITY;
-}
-
FstabEntry BuildGsiSystemFstabEntry() {
FstabEntry system = {
.blk_device = "system_gsi",
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 2c4299a..c7d2cb9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -564,9 +564,8 @@
if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts;
// confirm that fstab is missing system
- if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
- return entry.mount_point == "/" || entry.mount_point == "/system ";
- }) != fstab->end()) {
+ if (GetEntryForMountPoint(fstab, "/") != nullptr ||
+ GetEntryForMountPoint(fstab, "/system") != nullptr) {
return mounts;
}
@@ -847,9 +846,7 @@
std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab) {
if (fs_mgr_overlayfs_invalid()) return {};
- if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
- return entry.mount_point == kScratchMountPoint;
- }) != fstab->end()) {
+ if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
return {};
}
@@ -889,9 +886,7 @@
if (overlay_mount_point == kScratchMountPoint) {
if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
} else {
- if (std::find_if(fstab.begin(), fstab.end(), [&overlay_mount_point](const auto& entry) {
- return entry.mount_point == overlay_mount_point;
- }) == fstab.end()) {
+ if (GetEntryForMountPoint(&fstab, overlay_mount_point) == nullptr) {
continue;
}
}
diff --git a/fs_mgr/fs_mgr_roots.cpp b/fs_mgr/fs_mgr_roots.cpp
index 32a5d21..58ef9b6 100644
--- a/fs_mgr/fs_mgr_roots.cpp
+++ b/fs_mgr/fs_mgr_roots.cpp
@@ -37,9 +37,8 @@
if (path.empty()) return nullptr;
std::string str(path);
while (true) {
- auto it = std::find_if(fstab->begin(), fstab->end(),
- [&str](const auto& entry) { return entry.mount_point == str; });
- if (it != fstab->end()) return &*it;
+ auto entry = GetEntryForMountPoint(fstab, str);
+ if (entry != nullptr) return entry;
if (str == "/") break;
auto slash = str.find_last_of('/');
if (slash == std::string::npos) break;
@@ -65,10 +64,8 @@
return MountState::ERROR;
}
- auto mv = std::find_if(
- mounted_fstab.begin(), mounted_fstab.end(),
- [&mount_point](const auto& entry) { return entry.mount_point == mount_point; });
- if (mv != mounted_fstab.end()) {
+ auto mv = GetEntryForMountPoint(&mounted_fstab, mount_point);
+ if (mv != nullptr) {
return MountState::MOUNTED;
}
return MountState::NOT_MOUNTED;
@@ -178,9 +175,8 @@
return "";
}
- auto it = std::find_if(fstab.begin(), fstab.end(),
- [](const auto& entry) { return entry.mount_point == kSystemRoot; });
- if (it == fstab.end()) {
+ auto entry = GetEntryForMountPoint(&fstab, kSystemRoot);
+ if (entry == nullptr) {
return "/";
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index e87332f..2934363 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -65,9 +65,11 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
#define FS_MGR_DOMNT_SUCCESS 0
-
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
+ bool needs_checkpoint);
+int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
+int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
bool need_cp);
int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point = "");
int fs_mgr_do_mount_one(fstab_rec* rec);
@@ -79,7 +81,6 @@
std::function<void(const std::string& mount_point, int mode)> callback);
bool fs_mgr_swapon_all(const Fstab& fstab);
bool fs_mgr_update_logical_partition(FstabEntry* entry);
-bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
int fs_mgr_do_format(const FstabEntry& entry, bool reserve_footer);
int fs_mgr_do_format(fstab_rec* rec, bool reserve_footer);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 9c4d2da..549ff68 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -54,8 +54,8 @@
int max_comp_streams;
off64_t zram_size;
off64_t reserved_size;
- int file_contents_mode;
- int file_names_mode;
+ char* file_contents_mode;
+ char* file_names_mode;
off64_t erase_blk_size;
off64_t logical_blk_size;
char* sysfs_path;
@@ -69,33 +69,22 @@
struct fstab* fs_mgr_read_fstab(const char* fstab_path);
void fs_mgr_free_fstab(struct fstab* fstab);
-int fs_mgr_add_entry(struct fstab* fstab, const char* mount_point, const char* fs_type,
- const char* blk_device);
struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path);
int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab);
int fs_mgr_is_nonremovable(const struct fstab_rec* fstab);
int fs_mgr_is_verified(const struct fstab_rec* fstab);
-int fs_mgr_is_verifyatboot(const struct fstab_rec* fstab);
-int fs_mgr_is_avb(const struct fstab_rec* fstab);
int fs_mgr_is_encryptable(const struct fstab_rec* fstab);
-int fs_mgr_is_file_encrypted(const struct fstab_rec* fstab);
void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
const char** filenames_mode_ret);
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec* fstab);
int fs_mgr_is_noemulatedsd(const struct fstab_rec* fstab);
int fs_mgr_is_notrim(const struct fstab_rec* fstab);
-int fs_mgr_is_formattable(const struct fstab_rec* fstab);
-int fs_mgr_is_slotselect(const struct fstab_rec* fstab);
-int fs_mgr_is_nofail(const struct fstab_rec* fstab);
-int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab);
-int fs_mgr_is_latemount(const struct fstab_rec* fstab);
int fs_mgr_is_quota(const struct fstab_rec* fstab);
int fs_mgr_is_logical(const struct fstab_rec* fstab);
int fs_mgr_is_checkpoint(const struct fstab_rec* fstab);
int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
-int fs_mgr_is_fs_verity(const struct fstab_rec* fstab);
std::string fs_mgr_get_slot_suffix();
std::string fs_mgr_get_other_slot_suffix();
@@ -118,19 +107,20 @@
int max_comp_streams = 0;
off64_t zram_size = 0;
off64_t reserved_size = 0;
- int file_contents_mode = 0;
- int file_names_mode = 0;
+ std::string file_contents_mode;
+ std::string file_names_mode;
off64_t erase_blk_size = 0;
off64_t logical_blk_size = 0;
std::string sysfs_path;
std::string vbmeta_partition;
std::string zram_loopback_path;
- uint64_t zram_loopback_size;
+ uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default;
std::string zram_backing_dev_path;
+ std::string avb_key;
// TODO: Remove this union once fstab_rec is deprecated. It only serves as a
// convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
- union {
+ union FsMgrFlags {
uint64_t val;
struct {
// bit 0
@@ -195,6 +185,8 @@
bool ReadFstabFromDt(Fstab* fstab, bool log = true);
bool ReadDefaultFstab(Fstab* fstab);
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
+
// Temporary conversion functions.
FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
index 191e803..3e93265 100644
--- a/fs_mgr/libfs_avb/Android.bp
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -88,6 +88,7 @@
cc_test_host {
name: "libfs_avb_test",
defaults: ["libfs_avb_host_test_defaults"],
+ test_suites: ["general-tests"],
static_libs: [
"libfs_avb_test_util",
],
@@ -103,6 +104,7 @@
cc_test_host {
name: "libfs_avb_internal_test",
defaults: ["libfs_avb_host_test_defaults"],
+ test_suites: ["general-tests"],
static_libs: [
"libfs_avb_test_util",
],
diff --git a/fs_mgr/libfs_avb/TEST_MAPPING b/fs_mgr/libfs_avb/TEST_MAPPING
new file mode 100644
index 0000000..dc23827
--- /dev/null
+++ b/fs_mgr/libfs_avb/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "libfs_avb_test",
+ "host": true
+ },
+ {
+ "name": "libfs_avb_internal_test",
+ "host": true
+ }
+ ]
+}
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index f57c9d6..945087f 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -27,6 +27,7 @@
#include "util.h"
+using android::base::Basename;
using android::base::StartsWith;
using android::base::unique_fd;
@@ -61,7 +62,7 @@
// class VBMetaData
// ----------------
std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) {
- auto vbmeta_header(std::make_unique<AvbVBMetaImageHeader>());
+ auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>();
if (!vbmeta_header) return nullptr;
@@ -136,7 +137,7 @@
}
table.set_readonly(true);
- const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
+ const std::string mount_point(Basename(fstab_entry->mount_point));
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
if (!dm.CreateDevice(mount_point, table)) {
LERROR << "Couldn't create verity device!";
@@ -163,12 +164,12 @@
return true;
}
-bool GetHashtreeDescriptor(const std::string& partition_name,
- const std::vector<VBMetaData>& vbmeta_images,
- AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
- std::string* out_digest) {
+std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
+ const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
+ std::string* out_salt, std::string* out_digest) {
bool found = false;
const uint8_t* desc_partition_name;
+ auto hashtree_desc = std::make_unique<AvbHashtreeDescriptor>();
for (const auto& vbmeta : vbmeta_images) {
size_t num_descriptors;
@@ -189,15 +190,15 @@
desc_partition_name =
(const uint8_t*)descriptors[n] + sizeof(AvbHashtreeDescriptor);
if (!avb_hashtree_descriptor_validate_and_byteswap(
- (AvbHashtreeDescriptor*)descriptors[n], out_hashtree_desc)) {
+ (AvbHashtreeDescriptor*)descriptors[n], hashtree_desc.get())) {
continue;
}
- if (out_hashtree_desc->partition_name_len != partition_name.length()) {
+ if (hashtree_desc->partition_name_len != partition_name.length()) {
continue;
}
// Notes that desc_partition_name is not NUL-terminated.
std::string hashtree_partition_name((const char*)desc_partition_name,
- out_hashtree_desc->partition_name_len);
+ hashtree_desc->partition_name_len);
if (hashtree_partition_name == partition_name) {
found = true;
}
@@ -209,16 +210,43 @@
if (!found) {
LERROR << "Partition descriptor not found: " << partition_name.c_str();
+ return nullptr;
+ }
+
+ const uint8_t* desc_salt = desc_partition_name + hashtree_desc->partition_name_len;
+ *out_salt = BytesToHex(desc_salt, hashtree_desc->salt_len);
+
+ const uint8_t* desc_digest = desc_salt + hashtree_desc->salt_len;
+ *out_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len);
+
+ return hashtree_desc;
+}
+
+bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity_dev,
+ const std::vector<VBMetaData>& vbmeta_images,
+ const std::string& ab_suffix,
+ const std::string& ab_other_suffix) {
+ // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
+ // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
+ std::string partition_name = DeriveAvbPartitionName(*fstab_entry, ab_suffix, ab_other_suffix);
+
+ if (partition_name.empty()) {
+ LERROR << "partition name is empty, cannot lookup AVB descriptors";
return false;
}
- const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
- *out_salt = BytesToHex(desc_salt, out_hashtree_desc->salt_len);
+ std::string salt;
+ std::string root_digest;
+ std::unique_ptr<AvbHashtreeDescriptor> hashtree_descriptor =
+ GetHashtreeDescriptor(partition_name, vbmeta_images, &salt, &root_digest);
+ if (!hashtree_descriptor) {
+ return false;
+ }
- const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
- *out_digest = BytesToHex(desc_digest, out_hashtree_desc->root_digest_len);
-
- return true;
+ // Converts HASHTREE descriptor to verity table to load into kernel.
+ // When success, the new device path will be returned, e.g., /dev/block/dm-2.
+ return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, salt, root_digest,
+ wait_for_verity_dev);
}
// Converts a AVB partition_name (without A/B suffix) to a device partition name.
@@ -244,6 +272,38 @@
return sanitized_partition_name + append_suffix;
}
+// Converts fstab_entry.blk_device (with ab_suffix) to a AVB partition name.
+// e.g., "/dev/block/by-name/system_a", slot_select => "system",
+// "/dev/block/by-name/system_b", slot_select_other => "system_other".
+//
+// Or for a logical partition (with ab_suffix):
+// e.g., "system_a", slot_select => "system",
+// "system_b", slot_select_other => "system_other".
+std::string DeriveAvbPartitionName(const FstabEntry& fstab_entry, const std::string& ab_suffix,
+ const std::string& ab_other_suffix) {
+ std::string partition_name;
+ if (fstab_entry.fs_mgr_flags.logical) {
+ partition_name = fstab_entry.logical_partition_name;
+ } else {
+ partition_name = Basename(fstab_entry.blk_device);
+ }
+
+ if (fstab_entry.fs_mgr_flags.slot_select) {
+ auto found = partition_name.rfind(ab_suffix);
+ if (found != std::string::npos) {
+ partition_name.erase(found); // converts system_a => system
+ }
+ } else if (fstab_entry.fs_mgr_flags.slot_select_other) {
+ auto found = partition_name.rfind(ab_other_suffix);
+ if (found != std::string::npos) {
+ partition_name.erase(found); // converts system_b => system
+ }
+ partition_name += "_other"; // converts system => system_other
+ }
+
+ return partition_name;
+}
+
off64_t GetTotalSize(int fd) {
off64_t saved_current = lseek64(fd, 0, SEEK_CUR);
if (saved_current == -1) {
@@ -268,19 +328,19 @@
std::unique_ptr<AvbFooter> GetAvbFooter(int fd) {
std::array<uint8_t, AVB_FOOTER_SIZE> footer_buf;
- auto footer(std::make_unique<AvbFooter>());
+ auto footer = std::make_unique<AvbFooter>();
off64_t footer_offset = GetTotalSize(fd) - AVB_FOOTER_SIZE;
ssize_t num_read =
TEMP_FAILURE_RETRY(pread64(fd, footer_buf.data(), AVB_FOOTER_SIZE, footer_offset));
if (num_read < 0 || num_read != AVB_FOOTER_SIZE) {
- PERROR << "Failed to read AVB footer";
+ PERROR << "Failed to read AVB footer at offset: " << footer_offset;
return nullptr;
}
if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf.data(), footer.get())) {
- PERROR << "AVB footer verification failed.";
+ PERROR << "AVB footer verification failed at offset " << footer_offset;
return nullptr;
}
@@ -432,24 +492,22 @@
return chain_partitions;
}
-VBMetaVerifyResult LoadAndVerifyVbmetaImpl(
- const std::string& partition_name, const std::string& ab_suffix,
- const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
- bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
- std::function<std::string(const std::string&)> device_path_constructor,
- bool is_chained_vbmeta, std::vector<VBMetaData>* out_vbmeta_images) {
+// Loads the vbmeta from a given path.
+std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath(
+ const std::string& image_path, const std::string& partition_name,
+ const std::string& expected_public_key_blob, bool allow_verification_error,
+ bool rollback_protection, bool is_chained_vbmeta, bool* out_verification_disabled,
+ VBMetaVerifyResult* out_verify_result) {
// Ensures the device path (might be a symlink created by init) is ready to access.
- auto device_path = device_path_constructor(
- AvbPartitionToDevicePatition(partition_name, ab_suffix, ab_other_suffix));
- if (!WaitForFile(device_path, 1s)) {
- PERROR << "No such partition: " << device_path;
- return VBMetaVerifyResult::kError;
+ if (!WaitForFile(image_path, 1s)) {
+ PERROR << "No such path: " << image_path;
+ return nullptr;
}
- unique_fd fd(TEMP_FAILURE_RETRY(open(device_path.c_str(), O_RDONLY | O_CLOEXEC)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(image_path.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
- PERROR << "Failed to open: " << device_path;
- return VBMetaVerifyResult::kError;
+ PERROR << "Failed to open: " << image_path;
+ return nullptr;
}
VBMetaVerifyResult verify_result;
@@ -457,53 +515,84 @@
VerifyVBMetaData(fd, partition_name, expected_public_key_blob, &verify_result);
if (!vbmeta) {
LERROR << partition_name << ": Failed to load vbmeta, result: " << verify_result;
- return VBMetaVerifyResult::kError;
+ return nullptr;
}
+ vbmeta->set_vbmeta_path(image_path);
if (!allow_verification_error && verify_result == VBMetaVerifyResult::kErrorVerification) {
LERROR << partition_name << ": allow verification error is not allowed";
- return VBMetaVerifyResult::kError;
+ return nullptr;
}
std::unique_ptr<AvbVBMetaImageHeader> vbmeta_header =
vbmeta->GetVBMetaHeader(true /* update_vbmeta_size */);
if (!vbmeta_header) {
LERROR << partition_name << ": Failed to get vbmeta header";
- return VBMetaVerifyResult::kError;
+ return nullptr;
}
if (rollback_protection && RollbackDetected(partition_name, vbmeta_header->rollback_index)) {
- return VBMetaVerifyResult::kError;
+ return nullptr;
}
// vbmeta flags can only be set by the top-level vbmeta image.
if (is_chained_vbmeta && vbmeta_header->flags != 0) {
LERROR << partition_name << ": chained vbmeta image has non-zero flags";
- return VBMetaVerifyResult::kError;
+ return nullptr;
}
+ // Checks if verification has been disabled by setting a bit in the image.
+ if (out_verification_disabled) {
+ if (vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+ LWARNING << "VERIFICATION_DISABLED bit is set for partition: " << partition_name;
+ *out_verification_disabled = true;
+ } else {
+ *out_verification_disabled = false;
+ }
+ }
+
+ if (out_verify_result) {
+ *out_verify_result = verify_result;
+ }
+
+ return vbmeta;
+}
+
+VBMetaVerifyResult LoadAndVerifyVbmetaByPartition(
+ const std::string& partition_name, const std::string& ab_suffix,
+ const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
+ bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
+ std::function<std::string(const std::string&)> device_path_constructor, bool is_chained_vbmeta,
+ std::vector<VBMetaData>* out_vbmeta_images) {
+ auto image_path = device_path_constructor(
+ AvbPartitionToDevicePatition(partition_name, ab_suffix, ab_other_suffix));
+
+ bool verification_disabled = false;
+ VBMetaVerifyResult verify_result;
+ auto vbmeta = LoadAndVerifyVbmetaByPath(
+ image_path, partition_name, expected_public_key_blob, allow_verification_error,
+ rollback_protection, is_chained_vbmeta, &verification_disabled, &verify_result);
+
+ if (!vbmeta) {
+ return VBMetaVerifyResult::kError;
+ }
if (out_vbmeta_images) {
out_vbmeta_images->emplace_back(std::move(*vbmeta));
}
- // If verification has been disabled by setting a bit in the image, we're done.
- if (vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
- LWARNING << "VERIFICATION_DISABLED bit is set for partition: " << partition_name;
- return verify_result;
- }
-
- if (load_chained_vbmeta) {
+ // Only loads chained vbmeta if AVB verification is NOT disabled.
+ if (!verification_disabled && load_chained_vbmeta) {
bool fatal_error = false;
auto chain_partitions = GetChainPartitionInfo(*out_vbmeta_images->rbegin(), &fatal_error);
if (fatal_error) {
return VBMetaVerifyResult::kError;
}
for (auto& chain : chain_partitions) {
- auto sub_ret = LoadAndVerifyVbmetaImpl(
- chain.partition_name, ab_suffix, ab_other_suffix, chain.public_key_blob,
- allow_verification_error, load_chained_vbmeta, rollback_protection,
- device_path_constructor, true, /* is_chained_vbmeta */
- out_vbmeta_images);
+ auto sub_ret = LoadAndVerifyVbmetaByPartition(
+ chain.partition_name, ab_suffix, ab_other_suffix, chain.public_key_blob,
+ allow_verification_error, load_chained_vbmeta, rollback_protection,
+ device_path_constructor, true, /* is_chained_vbmeta */
+ out_vbmeta_images);
if (sub_ret != VBMetaVerifyResult::kSuccess) {
verify_result = sub_ret; // might be 'ERROR' or 'ERROR VERIFICATION'.
if (verify_result == VBMetaVerifyResult::kError) {
diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h
index babbfef..14918f2 100644
--- a/fs_mgr/libfs_avb/avb_util.h
+++ b/fs_mgr/libfs_avb/avb_util.h
@@ -46,10 +46,9 @@
};
// AvbHashtreeDescriptor to dm-verity table setup.
-bool GetHashtreeDescriptor(const std::string& partition_name,
- const std::vector<VBMetaData>& vbmeta_images,
- AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
- std::string* out_digest);
+std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
+ const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
+ std::string* out_salt, std::string* out_digest);
bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
const std::string& root_digest, const std::string& blk_device,
@@ -59,11 +58,20 @@
const std::string& salt, const std::string& root_digest,
bool wait_for_verity_dev);
-// Maps AVB partition name to a device partition name.
+// Searches a Avb hashtree descriptor in vbmeta_images for fstab_entry, to enable dm-verity.
+bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity_dev,
+ const std::vector<VBMetaData>& vbmeta_images,
+ const std::string& ab_suffix, const std::string& ab_other_suffix);
+
+// Converts AVB partition name to a device partition name.
std::string AvbPartitionToDevicePatition(const std::string& avb_partition_name,
const std::string& ab_suffix,
const std::string& ab_other_suffix);
+// Converts by-name symlink to AVB partition name.
+std::string DeriveAvbPartitionName(const FstabEntry& fstab_entry, const std::string& ab_suffix,
+ const std::string& ab_other_suffix);
+
// AvbFooter and AvbMetaImage maninpulations.
off64_t GetTotalSize(int fd);
@@ -84,12 +92,22 @@
// Extracts chain partition info.
std::vector<ChainInfo> GetChainPartitionInfo(const VBMetaData& vbmeta, bool* fatal_error);
-VBMetaVerifyResult LoadAndVerifyVbmetaImpl(
- const std::string& partition_name, const std::string& ab_suffix,
- const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
- bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
- std::function<std::string(const std::string&)> device_path_constructor,
- bool is_chained_vbmeta, std::vector<VBMetaData>* out_vbmeta_images);
+// Loads the single vbmeta from a given path.
+std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath(
+ const std::string& image_path, const std::string& partition_name,
+ const std::string& expected_public_key_blob, bool allow_verification_error,
+ bool rollback_protection, bool is_chained_vbmeta, bool* out_verification_disabled,
+ VBMetaVerifyResult* out_verify_result);
+
+// Loads the top-level vbmeta and all its chained vbmeta images.
+// The actual device path is constructed at runtime by:
+// partition_name, ab_suffix, ab_other_suffix, and device_path_constructor.
+VBMetaVerifyResult LoadAndVerifyVbmetaByPartition(
+ const std::string& partition_name, const std::string& ab_suffix,
+ const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
+ bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
+ std::function<std::string(const std::string&)> device_path_constructor, bool is_chained_vbmeta,
+ std::vector<VBMetaData>* out_vbmeta_images);
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index 9f8ad53..773baf4 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -233,10 +233,10 @@
auto device_path = custom_device_path ? custom_device_path : android_by_name_symlink;
- auto verify_result = LoadAndVerifyVbmetaImpl(
- partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
- load_chained_vbmeta, rollback_protection, device_path, false,
- /* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
+ auto verify_result = LoadAndVerifyVbmetaByPartition(
+ partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
+ load_chained_vbmeta, rollback_protection, device_path, false,
+ /* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
switch (verify_result) {
case VBMetaVerifyResult::kSuccess:
avb_handle->status_ = AvbHandleStatus::kSuccess;
@@ -245,10 +245,16 @@
avb_handle->status_ = AvbHandleStatus::kVerificationError;
break;
default:
- LERROR << "LoadAndVerifyVbmetaImpl failed, result: " << verify_result;
+ LERROR << "LoadAndVerifyVbmetaByPartition failed, result: " << verify_result;
return nullptr;
}
+ // Sanity check here because we have to use vbmeta_images_[0] below.
+ if (avb_handle->vbmeta_images_.size() < 1) {
+ LERROR << "LoadAndVerifyVbmetaByPartition failed, no vbmeta loaded";
+ return nullptr;
+ }
+
// Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
@@ -377,6 +383,54 @@
return avb_handle;
}
+AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry) {
+ if (fstab_entry->avb_key.empty()) {
+ LERROR << "avb_key=/path/to/key is missing for " << fstab_entry->mount_point;
+ return AvbHashtreeResult::kFail;
+ }
+
+ // Binds allow_verification_error and rollback_protection to device unlock state.
+ bool allow_verification_error = IsDeviceUnlocked();
+ bool rollback_protection = !allow_verification_error;
+
+ std::string expected_key_blob;
+ if (!ReadFileToString(fstab_entry->avb_key, &expected_key_blob)) {
+ if (!allow_verification_error) {
+ LERROR << "Failed to load avb_key: " << fstab_entry->avb_key
+ << " for mount point: " << fstab_entry->mount_point;
+ return AvbHashtreeResult::kFail;
+ }
+ // Use empty key blob, which means no expectation, if allow verification error.
+ expected_key_blob.clear();
+ }
+
+ bool verification_disabled = false;
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ fstab_entry->blk_device, "" /* partition_name, no need for a standalone path */,
+ expected_key_blob, allow_verification_error, rollback_protection,
+ false /* not is_chained_vbmeta */, &verification_disabled, nullptr /* out_verify_result */);
+
+ if (!vbmeta) {
+ LERROR << "Failed to load vbmeta: " << fstab_entry->blk_device;
+ return AvbHashtreeResult::kFail;
+ }
+
+ if (verification_disabled) {
+ LINFO << "AVB verification disabled on: " << fstab_entry->mount_point;
+ return AvbHashtreeResult::kDisabled;
+ }
+
+ // Puts the vbmeta into a vector, for LoadAvbHashtreeToEnableVerity() to use.
+ std::vector<VBMetaData> vbmeta_images;
+ vbmeta_images.emplace_back(std::move(*vbmeta));
+ if (!LoadAvbHashtreeToEnableVerity(fstab_entry, true /* wait_for_verity_dev */, vbmeta_images,
+ fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
+ return AvbHashtreeResult::kFail;
+ }
+
+ return AvbHashtreeResult::kSuccess;
+}
+
AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
if (!fstab_entry || status_ == AvbHandleStatus::kUninitialized || vbmeta_images_.size() < 1) {
return AvbHashtreeResult::kFail;
@@ -388,33 +442,8 @@
return AvbHashtreeResult::kDisabled;
}
- // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
- // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
- std::string partition_name;
- if (fstab_entry->fs_mgr_flags.logical) {
- partition_name = fstab_entry->logical_partition_name;
- } else {
- partition_name = Basename(fstab_entry->blk_device);
- }
-
- if (fstab_entry->fs_mgr_flags.slot_select) {
- auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
- if (ab_suffix != std::string::npos) {
- partition_name.erase(ab_suffix);
- }
- }
-
- AvbHashtreeDescriptor hashtree_descriptor;
- std::string salt;
- std::string root_digest;
- if (!GetHashtreeDescriptor(partition_name, vbmeta_images_, &hashtree_descriptor, &salt,
- &root_digest)) {
- return AvbHashtreeResult::kFail;
- }
-
- // Converts HASHTREE descriptor to verity_table_params.
- if (!HashtreeDmVeritySetup(fstab_entry, hashtree_descriptor, salt, root_digest,
- wait_for_verity_dev)) {
+ if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images_,
+ fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
return AvbHashtreeResult::kFail;
}
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index 7af3c7e..55a320e 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -81,8 +81,15 @@
// true to update vbmeta_size_ to the actual size with valid content.
std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false);
+ // Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file.
+ // e.g.,
+ // - /dev/block/by-name/system_a
+ // - /path/to/system_other.img.
+ void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); }
+
// Get methods for each data member.
const std::string& partition() const { return partition_name_; }
+ const std::string& vbmeta_path() const { return vbmeta_path_; }
uint8_t* data() const { return vbmeta_ptr_.get(); }
const size_t& size() const { return vbmeta_size_; }
@@ -93,6 +100,7 @@
std::unique_ptr<uint8_t[]> vbmeta_ptr_;
size_t vbmeta_size_;
std::string partition_name_;
+ std::string vbmeta_path_;
};
class FsManagerAvbOps;
@@ -160,6 +168,9 @@
// - kDisabled: hashtree is disabled.
AvbHashtreeResult SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev);
+ // Similar to above, but loads the offline vbmeta from the end of fstab_entry->blk_device.
+ static AvbHashtreeResult SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry);
+
const std::string& avb_version() const { return avb_version_; }
const VBMetaInfo& vbmeta_info() const { return vbmeta_info_; }
AvbHandleStatus status() const { return status_; }
diff --git a/fs_mgr/libfs_avb/tests/avb_util_test.cpp b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
index 26b3294..23faffc 100644
--- a/fs_mgr/libfs_avb/tests/avb_util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
@@ -14,20 +14,25 @@
* limitations under the License.
*/
+#include <endian.h>
+
#include <android-base/unique_fd.h>
#include <base/files/file_util.h>
#include <base/rand_util.h>
#include <base/strings/string_util.h>
+#include <libavb/libavb.h>
#include "avb_util.h"
#include "fs_avb_test_util.h"
// Target classes or functions to test:
using android::fs_mgr::AvbPartitionToDevicePatition;
+using android::fs_mgr::DeriveAvbPartitionName;
using android::fs_mgr::GetAvbFooter;
using android::fs_mgr::GetChainPartitionInfo;
using android::fs_mgr::GetTotalSize;
-using android::fs_mgr::LoadAndVerifyVbmetaImpl;
+using android::fs_mgr::LoadAndVerifyVbmetaByPartition;
+using android::fs_mgr::LoadAndVerifyVbmetaByPath;
using android::fs_mgr::VBMetaData;
using android::fs_mgr::VBMetaVerifyResult;
using android::fs_mgr::VerifyPublicKeyBlob;
@@ -52,8 +57,34 @@
// Loads the content of avb_image_path and comparies it with the content of vbmeta.
bool CompareVBMeta(const base::FilePath& avb_image_path, const VBMetaData& expected_vbmeta);
+
+ // Sets the flas in vbmeta header, the image_path could be a vbmeta.img or a system.img.
+ void SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags);
};
+void AvbUtilTest::SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags) {
+ if (!base::PathExists(image_path)) return;
+
+ std::string image_file_name = image_path.RemoveExtension().BaseName().value();
+ bool is_vbmeta_partition =
+ base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII);
+
+ android::base::unique_fd fd(open(image_path.value().c_str(), O_RDWR | O_CLOEXEC));
+ EXPECT_TRUE(fd > 0);
+
+ uint64_t vbmeta_offset = 0; // for vbmeta.img
+ if (!is_vbmeta_partition) {
+ std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
+ EXPECT_NE(nullptr, footer);
+ vbmeta_offset = footer->vbmeta_offset;
+ }
+
+ auto flags_offset = vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags);
+ uint32_t flags_data = htobe32(flags);
+ EXPECT_EQ(flags_offset, lseek64(fd, flags_offset, SEEK_SET));
+ EXPECT_EQ(sizeof flags_data, write(fd, &flags_data, sizeof flags_data));
+}
+
TEST_F(AvbUtilTest, AvbPartitionToDevicePatition) {
EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", ""));
EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", "_b"));
@@ -65,6 +96,63 @@
EXPECT_EQ("system_b", AvbPartitionToDevicePatition("system_other", "_a", "_b"));
}
+TEST_F(AvbUtilTest, DeriveAvbPartitionName) {
+ // The fstab_entry to test.
+ FstabEntry fstab_entry = {
+ .blk_device = "/dev/block/dm-1", // a dm-linear device (logical)
+ .mount_point = "/system",
+ .fs_type = "ext4",
+ .logical_partition_name = "system",
+ };
+
+ // Logical partitions.
+ // non-A/B
+ fstab_entry.fs_mgr_flags.logical = true;
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
+ // Active slot.
+ fstab_entry.fs_mgr_flags.slot_select = true;
+ fstab_entry.logical_partition_name = "system_a";
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
+ EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
+ // The other slot.
+ fstab_entry.fs_mgr_flags.slot_select = false;
+ fstab_entry.fs_mgr_flags.slot_select_other = true;
+ fstab_entry.logical_partition_name = "system_b";
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_b"));
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
+ EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_wont_erase_b"));
+
+ // Non-logical partitions.
+ // non-A/B.
+ fstab_entry.fs_mgr_flags.logical = false;
+ fstab_entry.fs_mgr_flags.slot_select = false;
+ fstab_entry.fs_mgr_flags.slot_select_other = false;
+ fstab_entry.blk_device = "/dev/block/by-name/system";
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
+ // Active slot _a.
+ fstab_entry.fs_mgr_flags.slot_select = true;
+ fstab_entry.blk_device = "/dev/block/by-name/system_a";
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
+ EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
+ // Inactive slot _b.
+ fstab_entry.fs_mgr_flags.slot_select = false;
+ fstab_entry.fs_mgr_flags.slot_select_other = true;
+ fstab_entry.blk_device = "/dev/block/by-name/system_b";
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_b"));
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
+ EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
+ EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_wont_erase_b"));
+}
+
TEST_F(AvbUtilTest, GetFdTotalSize) {
// Generates a raw test.img via BaseFsAvbTest.
const size_t image_size = 5 * 1024 * 1024;
@@ -751,7 +839,213 @@
EXPECT_EQ(false, fatal_error);
}
-TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImpl) {
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPath) {
+ // Generates a raw system_other.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
+
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
+ 20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+
+ std::string expected_key_blob_4096;
+ EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
+
+ bool verification_disabled;
+ VBMetaVerifyResult verify_result;
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
+
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
+ EXPECT_EQ(false, verification_disabled);
+
+ EXPECT_EQ(2112UL, vbmeta->size());
+ EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
+ EXPECT_EQ("system_other", vbmeta->partition());
+ EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
+}
+
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathErrorVerification) {
+ // Generates a raw system_other.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
+
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
+ 20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+
+ std::string expected_key_blob_4096;
+ EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
+
+ // Modifies the auxiliary data of system_other.img
+ auto fd = OpenUniqueReadFd(system_path);
+ auto system_footer = GetAvbFooter(fd);
+ auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system_other-vbmeta.img");
+ auto system_header = system_vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
+ size_t header_block_offset = 0;
+ size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
+ size_t auxiliary_block_offset =
+ authentication_block_offset + system_header->authentication_data_block_size;
+
+ // Modifies the hash.
+ ModifyFile(
+ system_path,
+ (system_footer->vbmeta_offset + authentication_block_offset + system_header->hash_offset),
+ system_header->hash_size);
+
+ VBMetaVerifyResult verify_result;
+ // Not allow verification error.
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_EQ(nullptr, vbmeta);
+
+ // Allow verification error.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ true /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
+
+ EXPECT_EQ(2112UL, vbmeta->size());
+ EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
+ EXPECT_EQ("system_other", vbmeta->partition());
+ EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
+
+ // Modifies the auxiliary data block.
+ ModifyFile(system_path, system_footer->vbmeta_offset + auxiliary_block_offset,
+ system_header->auxiliary_data_block_size);
+
+ // Not allow verification error.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_EQ(nullptr, vbmeta);
+
+ // Allow verification error.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ true /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
+}
+
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathUnexpectedPublicKey) {
+ // Generates a raw system_other.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
+
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
+ 20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ base::FilePath rsa2048_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+
+ std::string expected_key_blob_4096;
+ EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
+ std::string unexpected_key_blob_2048;
+ EXPECT_TRUE(base::ReadFileToString(rsa2048_public_key, &unexpected_key_blob_2048));
+
+ // Uses the correct expected public key.
+ VBMetaVerifyResult verify_result;
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(verify_result, VBMetaVerifyResult::kSuccess);
+ EXPECT_EQ(2112UL, vbmeta->size());
+ EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
+ EXPECT_EQ("system_other", vbmeta->partition());
+ EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
+
+ // Uses the wrong expected public key with allow_verification_error set to false.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", unexpected_key_blob_2048,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_EQ(nullptr, vbmeta);
+
+ // Uses the wrong expected public key with allow_verification_error set to true.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", unexpected_key_blob_2048,
+ true /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(verify_result, VBMetaVerifyResult::kErrorVerification);
+ EXPECT_EQ(2112UL, vbmeta->size());
+ EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
+ EXPECT_EQ("system_other", vbmeta->partition());
+ EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
+}
+
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathVerificationDisabled) {
+ // Generates a raw system_other.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
+
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
+ 20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+
+ std::string expected_key_blob_4096;
+ EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
+
+ // Sets disabled flag and expect the returned verification_disabled is true.
+ SetVBMetaFlags(system_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
+ bool verification_disabled;
+ VBMetaVerifyResult verify_result;
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ true /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
+
+ EXPECT_NE(nullptr, vbmeta);
+ EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
+ EXPECT_EQ(true, verification_disabled); // should be true.
+
+ EXPECT_EQ(2112UL, vbmeta->size());
+ EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
+ EXPECT_EQ("system_other", vbmeta->partition());
+ EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
+
+ // Since the vbmeta flags is modified, vbmeta will be nullptr
+ // if verification error isn't allowed.
+ vbmeta = LoadAndVerifyVbmetaByPath(
+ system_path.value(), "system_other", expected_key_blob_4096,
+ false /* allow_verification_error */, false /* rollback_protection */,
+ false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
+ EXPECT_EQ(nullptr, vbmeta);
+}
+
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartition) {
// Generates a raw boot.img
const size_t boot_image_size = 5 * 1024 * 1024;
const size_t boot_partition_size = 10 * 1024 * 1024;
@@ -795,18 +1089,18 @@
EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
CalcVBMetaDigest("vbmeta.img", "sha256"));
- // Starts to test LoadAndVerifyVbmetaImpl.
+ // Starts to test LoadAndVerifyVbmetaByPartition.
std::vector<VBMetaData> vbmeta_images;
auto vbmeta_image_path = [this](const std::string& partition_name) {
return test_dir_.Append(partition_name + ".img").value();
};
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
// Binary comparison for each vbmeta image.
@@ -818,17 +1112,17 @@
// Skip loading chained vbmeta images.
vbmeta_images.clear();
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- false /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ false /* load_chained_vbmeta */, true /* rollback_protection */,
+ vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
// Only vbmeta is loaded.
EXPECT_EQ(1UL, vbmeta_images.size());
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
}
-TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplWithSuffixes) {
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionWithSuffixes) {
// Tests the following chained partitions.
// vbmeta_a.img
// |--> boot_b.img (boot_other)
@@ -874,18 +1168,18 @@
{"vbmeta_system_other", 2, rsa4096_public_key}},
"--internal_release_string \"unit test\"");
- // Starts to test LoadAndVerifyVbmetaImpl with ab_suffix and ab_other_suffix.
+ // Starts to test LoadAndVerifyVbmetaByPartition with ab_suffix and ab_other_suffix.
auto vbmeta_image_path = [this](const std::string& partition_name) {
return test_dir_.Append(partition_name + ".img").value();
};
std::vector<VBMetaData> vbmeta_images;
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot_other, vbmeta_system_other and system
// Binary comparison for each vbmeta image.
@@ -897,26 +1191,26 @@
// Skips loading chained vbmeta images.
vbmeta_images.clear();
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- false /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ false /* load_chained_vbmeta */, true /* rollback_protection */,
+ vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
// Only vbmeta is loaded.
EXPECT_EQ(1UL, vbmeta_images.size());
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
// Using an invalid suffix for 'other' slot, checks it returns error.
EXPECT_EQ(VBMetaVerifyResult::kError,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "_a" /* ab_suffix */,
- "_invalid_suffix" /* other_suffix */, "" /* expected_public_key_blob*/,
- false /* allow_verification_error */, true /* load_chained_vbmeta */,
- true /* rollback_protection */, vbmeta_image_path,
- false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "_a" /* ab_suffix */,
+ "_invalid_suffix" /* other_suffix */, "" /* expected_public_key_blob*/,
+ false /* allow_verification_error */, true /* load_chained_vbmeta */,
+ true /* rollback_protection */, vbmeta_image_path, false /* is_chained_vbmeta*/,
+ &vbmeta_images));
}
-TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplErrorVerification) {
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionErrorVerification) {
// Generates a raw boot.img
const size_t boot_image_size = 5 * 1024 * 1024;
const size_t boot_partition_size = 10 * 1024 * 1024;
@@ -964,27 +1258,27 @@
// Modifies the hash.
ModifyFile(vbmeta_path, authentication_block_offset + header->hash_offset, header->hash_size);
- // Starts to test LoadAndVerifyVbmetaImpl.
+ // Starts to test LoadAndVerifyVbmetaByPartition.
std::vector<VBMetaData> vbmeta_images;
auto vbmeta_image_path = [this](const std::string& partition_name) {
return test_dir_.Append(partition_name + ".img").value();
};
EXPECT_EQ(VBMetaVerifyResult::kError,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
// Stops to load vbmeta because the top-level vbmeta has verification error.
EXPECT_EQ(0UL, vbmeta_images.size());
// Tries again with verification error allowed.
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "", /* other_suffix */
- "" /* expected_public_key_blob*/, true /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "", /* other_suffix */
+ "" /* expected_public_key_blob*/, true /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
EXPECT_EQ(3UL, vbmeta_images.size()); // vbmeta, boot, and system
// Binary comparison for each vbmeta image.
@@ -1008,11 +1302,11 @@
system_header->auxiliary_data_block_size);
vbmeta_images.clear();
EXPECT_EQ(VBMetaVerifyResult::kError,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- "" /* expected_public_key_blob*/, false /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
// 'vbmeta', 'boot' but no 'system', because of verification error.
EXPECT_EQ(2UL, vbmeta_images.size());
// Binary comparison for the loaded 'vbmeta' and 'boot'.
@@ -1020,20 +1314,113 @@
EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
// Resets the modification of the auxiliary data.
- ModifyFile(vbmeta_path, 0 /* offset */, -1 /* length */);
+ ModifyFile(system_path, 0 /* offset */, -1 /* length */);
// Sets the vbmeta header flags on a chained partition, which introduces an error.
ModifyFile(system_path, system_footer->vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags),
sizeof(uint32_t));
EXPECT_EQ(VBMetaVerifyResult::kError,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- "" /* expected_public_key_blob*/, true /* allow_verification_error */,
- true /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, true /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
}
-TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplUnexpectedPublicKey) {
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionVerificationDisabled) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
+ data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates chain partition descriptors.
+ base::FilePath rsa2048_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+ // Makes a vbmeta_system.img including the 'system' chained descriptor.
+ auto vbmeta_system_path = GenerateVBMetaImage(
+ "vbmeta_system.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
+ {}, /* include_descriptor_image_paths */
+ {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+
+ // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
+ auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
+ data_dir_.Append("testkey_rsa8192.pem"),
+ {}, /* include_descriptor_image_paths */
+ {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
+ {"vbmeta_system", 2, rsa4096_public_key}},
+ "--internal_release_string \"unit test\"");
+
+ // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
+ EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+
+ // Starts to test LoadAndVerifyVbmetaByPartition.
+ std::vector<VBMetaData> vbmeta_images;
+ auto vbmeta_image_path = [this](const std::string& partition_name) {
+ return test_dir_.Append(partition_name + ".img").value();
+ };
+
+ EXPECT_EQ(VBMetaVerifyResult::kSuccess,
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, false /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
+
+ EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
+ // Binary comparison for each vbmeta image.
+ EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
+ EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
+ EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
+ EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
+
+ // Sets VERIFICATION_DISABLED to the top-level vbmeta.img
+ SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
+ vbmeta_images.clear();
+ EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, true /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
+ EXPECT_EQ(1UL, vbmeta_images.size()); // Only vbmeta is loaded
+ EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
+
+ // HASHTREE_DISABLED still loads the chained vbmeta.
+ SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+ vbmeta_images.clear();
+ EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ "" /* expected_public_key_blob*/, true /* allow_verification_error */,
+ true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
+ false /* is_chained_vbmeta*/, &vbmeta_images));
+ EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
+ // Binary comparison for each vbmeta image.
+ EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
+ EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
+ EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
+ EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
+}
+
+TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionUnexpectedPublicKey) {
// Generates chain partition descriptors.
base::FilePath rsa2048_public_key =
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
@@ -1060,29 +1447,29 @@
std::vector<VBMetaData> vbmeta_images;
// Uses the correct expected public key.
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- expected_key_blob_8192, true /* allow_verification_error */,
- false /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ expected_key_blob_8192, true /* allow_verification_error */,
+ false /* load_chained_vbmeta */, true /* rollback_protection */,
+ vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
// Uses the wrong expected public key with allow_verification_error set to true.
vbmeta_images.clear();
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- expected_key_blob_4096, true /* allow_verification_error */,
- false /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ expected_key_blob_4096, true /* allow_verification_error */,
+ false /* load_chained_vbmeta */, true /* rollback_protection */,
+ vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
// Uses the wrong expected public key with allow_verification_error set to false.
vbmeta_images.clear();
EXPECT_EQ(VBMetaVerifyResult::kError,
- LoadAndVerifyVbmetaImpl(
- "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
- expected_key_blob_4096, false /* allow_verification_error */,
- false /* load_chained_vbmeta */, true /* rollback_protection */,
- vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
+ LoadAndVerifyVbmetaByPartition(
+ "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
+ expected_key_blob_4096, false /* allow_verification_error */,
+ false /* load_chained_vbmeta */, true /* rollback_protection */,
+ vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
}
} // namespace fs_avb_host_test
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 8f08169..69724f8 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -442,10 +442,6 @@
}
TEST_F(BuilderTest, block_device_info) {
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- ASSERT_NE(fstab, nullptr);
-
PartitionOpener opener;
BlockDeviceInfo device_info;
diff --git a/fs_mgr/tests/data/fstab.example b/fs_mgr/tests/data/fstab.example
index 1a3dfa1..aebce32 100644
--- a/fs_mgr/tests/data/fstab.example
+++ b/fs_mgr/tests/data/fstab.example
@@ -9,3 +9,7 @@
/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
/devices/platform/soc/a600000.ssusb/a600000.dwc3* auto vfat defaults voldmanaged=usb:auto
/dev/block/zram0 none swap defaults zramsize=1073741824,max_comp_streams=8
+/dev/block/zram0 none2 swap nodiratime,remount,bind zramsize=1073741824,max_comp_streams=8
+/dev/block/zram0 none3 swap unbindable,private,slave zramsize=1073741824,max_comp_streams=8
+/dev/block/zram0 none4 swap noexec,shared,rec zramsize=1073741824,max_comp_streams=8
+/dev/block/zram0 none5 swap rw zramsize=1073741824,max_comp_streams=8
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 4582401..e2b283a 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -201,32 +201,823 @@
EXPECT_EQ(i, fstab.size());
}
-TEST(fs_mgr, ReadFstabFromFile_FsOptions) {
+TEST(fs_mgr, ReadFstabFromFile_MountOptions) {
Fstab fstab;
std::string fstab_file = android::base::GetExecutableDirectory() + "/data/fstab.example";
EXPECT_TRUE(ReadFstabFromFile(fstab_file, &fstab));
EXPECT_EQ("/", fstab[0].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_RDONLY), fstab[0].flags);
EXPECT_EQ("barrier=1", fstab[0].fs_options);
EXPECT_EQ("/metadata", fstab[1].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_NOATIME | MS_NOSUID | MS_NODEV), fstab[1].flags);
EXPECT_EQ("discard", fstab[1].fs_options);
EXPECT_EQ("/data", fstab[2].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_NOATIME | MS_NOSUID | MS_NODEV), fstab[2].flags);
EXPECT_EQ("discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier", fstab[2].fs_options);
EXPECT_EQ("/misc", fstab[3].mount_point);
+ EXPECT_EQ(0U, fstab[3].flags);
EXPECT_EQ("", fstab[3].fs_options);
EXPECT_EQ("/vendor/firmware_mnt", fstab[4].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_RDONLY), fstab[4].flags);
EXPECT_EQ(
"shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,"
"context=u:object_r:firmware_file:s0",
fstab[4].fs_options);
EXPECT_EQ("auto", fstab[5].mount_point);
+ EXPECT_EQ(0U, fstab[5].flags);
EXPECT_EQ("", fstab[5].fs_options);
EXPECT_EQ("none", fstab[6].mount_point);
+ EXPECT_EQ(0U, fstab[6].flags);
EXPECT_EQ("", fstab[6].fs_options);
+
+ EXPECT_EQ("none2", fstab[7].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_NODIRATIME | MS_REMOUNT | MS_BIND), fstab[7].flags);
+ EXPECT_EQ("", fstab[7].fs_options);
+
+ EXPECT_EQ("none3", fstab[8].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE), fstab[8].flags);
+ EXPECT_EQ("", fstab[8].fs_options);
+
+ EXPECT_EQ("none4", fstab[9].mount_point);
+ EXPECT_EQ(static_cast<unsigned long>(MS_NOEXEC | MS_SHARED | MS_REC), fstab[9].flags);
+ EXPECT_EQ("", fstab[9].fs_options);
+
+ EXPECT_EQ("none5", fstab[10].mount_point);
+ EXPECT_EQ(0U, fstab[10].flags); // rw is the same as defaults
+ EXPECT_EQ("", fstab[10].fs_options);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrFlags) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults wait,check,nonremovable,recoveryonly,verifyatboot,verify
+source none1 swap defaults avb,noemulatedsd,notrim,formattable,slotselect,nofail
+source none2 swap defaults first_stage_mount,latemount,quota,logical,slotselect_other
+source none3 swap defaults checkpoint=block
+source none4 swap defaults checkpoint=fs
+source none5 swap defaults defaults
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(6U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.wait = true;
+ flags.check = true;
+ flags.nonremovable = true;
+ flags.recovery_only = true;
+ flags.verify_at_boot = true;
+ flags.verify = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.avb = true;
+ flags.no_emulated_sd = true;
+ flags.no_trim = true;
+ flags.formattable = true;
+ flags.slot_select = true;
+ flags.no_fail = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.first_stage_mount = true;
+ flags.late_mount = true;
+ flags.quota = true;
+ flags.logical = true;
+ flags.slot_select_other = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.checkpoint_blk = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ entry++;
+
+ EXPECT_EQ("none4", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.checkpoint_fs = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ entry++;
+
+ EXPECT_EQ("none5", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_AllBad) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults encryptable,forceencrypt,fileencryption,forcefdeorfbe,keydirectory,length,swapprio,zramsize,max_comp_streams,reservedsize,eraseblk,logicalblk,sysfs_path,zram_loopback_path,zram_loopback_size,zram_backing_dev_path
+
+source none1 swap defaults encryptable=,forceencrypt=,fileencryption=,keydirectory=,length=,swapprio=,zramsize=,max_comp_streams=,verify=,avb=,reservedsize=,eraseblk=,logicalblk=,sysfs_path=,zram_loopback_path=,zram_loopback_size=,zram_backing_dev_path=
+
+source none2 swap defaults forcefdeorfbe=
+
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(3U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ EXPECT_EQ("", entry->key_loc);
+ EXPECT_EQ("", entry->key_dir);
+ EXPECT_EQ("", entry->verity_loc);
+ EXPECT_EQ(0, entry->length);
+ EXPECT_EQ("", entry->label);
+ EXPECT_EQ(-1, entry->partnum);
+ EXPECT_EQ(-1, entry->swap_prio);
+ EXPECT_EQ(0, entry->max_comp_streams);
+ EXPECT_EQ(0, entry->zram_size);
+ EXPECT_EQ(0, entry->reserved_size);
+ EXPECT_EQ("", entry->file_contents_mode);
+ EXPECT_EQ("", entry->file_names_mode);
+ EXPECT_EQ(0, entry->erase_blk_size);
+ EXPECT_EQ(0, entry->logical_blk_size);
+ EXPECT_EQ("", entry->sysfs_path);
+ EXPECT_EQ("", entry->zram_loopback_path);
+ EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
+ EXPECT_EQ("", entry->zram_backing_dev_path);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.crypt = true;
+ flags.force_crypt = true;
+ flags.file_encryption = true;
+ flags.key_directory = true;
+ flags.length = true;
+ flags.swap_prio = true;
+ flags.zram_size = true;
+ flags.max_comp_streams = true;
+ flags.verify = true;
+ flags.avb = true;
+ flags.reserved_size = true;
+ flags.erase_blk_size = true;
+ flags.logical_blk_size = true;
+ flags.sysfs = true;
+ flags.zram_loopback_path = true;
+ flags.zram_loopback_size = true;
+ flags.zram_backing_dev_path = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ EXPECT_EQ("", entry->key_loc);
+ EXPECT_EQ("", entry->key_dir);
+ EXPECT_EQ("", entry->verity_loc);
+ EXPECT_EQ(0, entry->length);
+ EXPECT_EQ("", entry->label);
+ EXPECT_EQ(-1, entry->partnum);
+ EXPECT_EQ(-1, entry->swap_prio);
+ EXPECT_EQ(0, entry->max_comp_streams);
+ EXPECT_EQ(0, entry->zram_size);
+ EXPECT_EQ(0, entry->reserved_size);
+ EXPECT_EQ("", entry->file_contents_mode);
+ EXPECT_EQ("", entry->file_names_mode);
+ EXPECT_EQ(0, entry->erase_blk_size);
+ EXPECT_EQ(0, entry->logical_blk_size);
+ EXPECT_EQ("", entry->sysfs_path);
+ EXPECT_EQ("", entry->zram_loopback_path);
+ EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
+ EXPECT_EQ("", entry->zram_backing_dev_path);
+ entry++;
+
+ // forcefdeorfbe sets file_contents_mode and file_names_mode by default, so test it separately.
+ EXPECT_EQ("none2", entry->mount_point);
+ {
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.force_fde_or_fbe = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ }
+ EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+ EXPECT_EQ("", entry->key_loc);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Encryptable) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults encryptable=/dir/key
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.crypt = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("/dir/key", entry->key_loc);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_VoldManaged) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults voldmanaged=:
+source none1 swap defaults voldmanaged=sdcard
+source none2 swap defaults voldmanaged=sdcard:3
+source none3 swap defaults voldmanaged=sdcard:auto
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(4U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.vold_managed = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(entry->label.empty());
+ EXPECT_EQ(-1, entry->partnum);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(entry->label.empty());
+ EXPECT_EQ(-1, entry->partnum);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("sdcard", entry->label);
+ EXPECT_EQ(3, entry->partnum);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("sdcard", entry->label);
+ EXPECT_EQ(-1, entry->partnum);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Length) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults length=blah
+source none1 swap defaults length=123456
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(2U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.length = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->length);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(123456, entry->length);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Swapprio) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults swapprio=blah
+source none1 swap defaults swapprio=123456
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(2U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.swap_prio = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(-1, entry->swap_prio);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(123456, entry->swap_prio);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ZramSize) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults zramsize=blah
+source none1 swap defaults zramsize=123456
+source none2 swap defaults zramsize=blah%
+source none3 swap defaults zramsize=5%
+source none4 swap defaults zramsize=105%
+source none5 swap defaults zramsize=%
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(6U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.zram_size = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(123456, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_NE(0, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none4", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none5", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->zram_size);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Verify) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults verify=/dir/key
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.verify = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("/dir/key", entry->verity_loc);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ForceEncrypt) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults forceencrypt=/dir/key
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.force_crypt = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("/dir/key", entry->key_loc);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ForceFdeOrFbe) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults forcefdeorfbe=/dir/key
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.force_fde_or_fbe = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("/dir/key", entry->key_loc);
+ EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_FileEncryption) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults fileencryption=blah
+source none1 swap defaults fileencryption=software
+source none2 swap defaults fileencryption=aes-256-xts
+source none3 swap defaults fileencryption=adiantum
+source none4 swap defaults fileencryption=adiantum:aes-256-heh
+source none5 swap defaults fileencryption=ice
+source none6 swap defaults fileencryption=ice:blah
+source none7 swap defaults fileencryption=ice:aes-256-cts
+source none8 swap defaults fileencryption=ice:aes-256-heh
+source none9 swap defaults fileencryption=ice:adiantum
+source none10 swap defaults fileencryption=ice:adiantum:
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(11U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.file_encryption = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("", entry->file_contents_mode);
+ EXPECT_EQ("", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("adiantum", entry->file_contents_mode);
+ EXPECT_EQ("adiantum", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none4", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("adiantum", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-heh", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none5", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("ice", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none6", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("ice", entry->file_contents_mode);
+ EXPECT_EQ("", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none7", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("ice", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none8", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("ice", entry->file_contents_mode);
+ EXPECT_EQ("aes-256-heh", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none9", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("ice", entry->file_contents_mode);
+ EXPECT_EQ("adiantum", entry->file_names_mode);
+
+ entry++;
+ EXPECT_EQ("none10", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ("", entry->file_contents_mode);
+ EXPECT_EQ("", entry->file_names_mode);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_MaxCompStreams) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults max_comp_streams=blah
+source none1 swap defaults max_comp_streams=123456
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(2U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.max_comp_streams = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->max_comp_streams);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(123456, entry->max_comp_streams);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ReservedSize) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults reservedsize=blah
+source none1 swap defaults reservedsize=2
+source none2 swap defaults reservedsize=1K
+source none3 swap defaults reservedsize=2m
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(4U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.reserved_size = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->reserved_size);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(2, entry->reserved_size);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(1024, entry->reserved_size);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(2 * 1024 * 1024, entry->reserved_size);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_EraseBlk) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults eraseblk=blah
+source none1 swap defaults eraseblk=4000
+source none2 swap defaults eraseblk=5000
+source none3 swap defaults eraseblk=8192
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(4U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.erase_blk_size = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->erase_blk_size);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->erase_blk_size);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->erase_blk_size);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(8192, entry->erase_blk_size);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Logicalblk) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults logicalblk=blah
+source none1 swap defaults logicalblk=4000
+source none2 swap defaults logicalblk=5000
+source none3 swap defaults logicalblk=8192
+)fs";
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(4U, fstab.size());
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.logical_blk_size = true;
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->logical_blk_size);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->logical_blk_size);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(0, entry->logical_blk_size);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_EQ(8192, entry->logical_blk_size);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Avb) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults avb=vbmeta_partition
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.avb = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("vbmeta_partition", entry->vbmeta_partition);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_KeyDirectory) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults keydirectory=/dir/key
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.key_directory = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("/dir/key", entry->key_dir);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_SysfsPath) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults sysfs_path=/sys/device
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(1U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+
+ FstabEntry::FsMgrFlags flags = {0};
+ flags.sysfs = true;
+ EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+
+ EXPECT_EQ("/sys/device", entry->sysfs_path);
+}
+
+TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Zram) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ std::string fstab_contents = R"fs(
+source none0 swap defaults zram_loopback_path=/dev/path
+
+source none1 swap defaults zram_loopback_size=blah
+source none2 swap defaults zram_loopback_size=2
+source none3 swap defaults zram_loopback_size=1K
+source none4 swap defaults zram_loopback_size=2m
+
+source none5 swap defaults zram_backing_dev_path=/dev/path2
+
+)fs";
+
+ ASSERT_TRUE(android::base::WriteStringToFd(fstab_contents, tf.fd));
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
+ ASSERT_EQ(6U, fstab.size());
+
+ auto entry = fstab.begin();
+ EXPECT_EQ("none0", entry->mount_point);
+ EXPECT_EQ("/dev/path", entry->zram_loopback_path);
+ entry++;
+
+ EXPECT_EQ("none1", entry->mount_point);
+ EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
+ entry++;
+
+ EXPECT_EQ("none2", entry->mount_point);
+ EXPECT_EQ(2U, entry->zram_loopback_size);
+ entry++;
+
+ EXPECT_EQ("none3", entry->mount_point);
+ EXPECT_EQ(1024U, entry->zram_loopback_size);
+ entry++;
+
+ EXPECT_EQ("none4", entry->mount_point);
+ EXPECT_EQ(2U * 1024U * 1024U, entry->zram_loopback_size);
+ entry++;
+
+ EXPECT_EQ("none5", entry->mount_point);
+ EXPECT_EQ("/dev/path2", entry->zram_backing_dev_path);
}
diff --git a/healthd/OWNERS b/healthd/OWNERS
index 00df08a..d3f8758 100644
--- a/healthd/OWNERS
+++ b/healthd/OWNERS
@@ -1,2 +1,2 @@
elsk@google.com
-toddpoynor@google.com
+hridya@google.com
diff --git a/healthd/animation.h b/healthd/animation.h
index f59fb38..9476c91 100644
--- a/healthd/animation.h
+++ b/healthd/animation.h
@@ -48,6 +48,25 @@
GRFont* font;
};
+ // When libminui loads PNG images:
+ // - When treating paths as relative paths, it adds ".png" suffix.
+ // - When treating paths as absolute paths, it doesn't add the suffix. Hence, the suffix
+ // is added here.
+ void set_resource_root(const std::string& root) {
+ if (!animation_file.empty()) {
+ animation_file = root + animation_file + ".png";
+ }
+ if (!fail_file.empty()) {
+ fail_file = root + fail_file + ".png";
+ }
+ if (!text_clock.font_file.empty()) {
+ text_clock.font_file = root + text_clock.font_file + ".png";
+ }
+ if (!text_percent.font_file.empty()) {
+ text_percent.font_file = root + text_percent.font_file + ".png";
+ }
+ }
+
std::string animation_file;
std::string fail_file;
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 2eb5497..8f2f727 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -80,8 +80,13 @@
#define LOGW(x...) KLOG_WARNING("charger", x);
#define LOGV(x...) KLOG_DEBUG("charger", x);
-static constexpr const char* animation_desc_path =
- "/res/values/charger/animation.txt";
+// Resources in /product/etc/res overrides resources in /res.
+// If the device is using the Generic System Image (GSI), resources may exist in
+// both paths.
+static constexpr const char* product_animation_desc_path =
+ "/product/etc/res/values/charger/animation.txt";
+static constexpr const char* product_animation_root = "/product/etc/res/images/";
+static constexpr const char* animation_desc_path = "/res/values/charger/animation.txt";
struct key_state {
bool pending;
@@ -600,7 +605,10 @@
bool parse_success;
std::string content;
- if (base::ReadFileToString(animation_desc_path, &content)) {
+ if (base::ReadFileToString(product_animation_desc_path, &content)) {
+ parse_success = parse_animation_desc(content, &battery_animation);
+ battery_animation.set_resource_root(product_animation_root);
+ } else if (base::ReadFileToString(animation_desc_path, &content)) {
parse_success = parse_animation_desc(content, &battery_animation);
} else {
LOGW("Could not open animation description at %s\n", animation_desc_path);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 3199d45..91b7ddd 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -49,8 +49,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <bootimg.h>
-#include <fs_mgr.h>
#include <property_info_parser/property_info_parser.h>
#include <property_info_serializer/property_info_serializer.h>
#include <selinux/android.h>
@@ -79,8 +77,6 @@
using android::properties::PropertyInfoAreaFile;
using android::properties::PropertyInfoEntry;
-#define RECOVERY_MOUNT_POINT "/recovery"
-
namespace android {
namespace init {
@@ -732,37 +728,6 @@
property_set("ro.persistent_properties.ready", "true");
}
-void load_recovery_id_prop() {
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) {
- PLOG(ERROR) << "unable to read default fstab";
- return;
- }
-
- fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), RECOVERY_MOUNT_POINT);
- if (rec == NULL) {
- LOG(ERROR) << "/recovery not specified in fstab";
- return;
- }
-
- int fd = open(rec->blk_device, O_RDONLY | O_CLOEXEC);
- if (fd == -1) {
- PLOG(ERROR) << "error opening block device " << rec->blk_device;
- return;
- }
-
- boot_img_hdr hdr;
- if (android::base::ReadFully(fd, &hdr, sizeof(hdr))) {
- std::string hex = bytes_to_hex(reinterpret_cast<uint8_t*>(hdr.id), sizeof(hdr.id));
- property_set("ro.recovery_id", hex);
- } else {
- PLOG(ERROR) << "error reading /recovery";
- }
-
- close(fd);
-}
-
void property_load_boot_defaults() {
// TODO(b/117892318): merge prop.default and build.prop files into one
// TODO(b/122864654): read the prop files from all partitions and then
@@ -783,7 +748,6 @@
load_properties_from_file("/odm/build.prop", NULL);
load_properties_from_file("/vendor/build.prop", NULL);
load_properties_from_file("/factory/factory.prop", "ro.*");
- load_recovery_id_prop();
update_sys_usb_config();
}
diff --git a/init/util.cpp b/init/util.cpp
index 3781141..80fb03d 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -34,7 +34,6 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
@@ -269,16 +268,6 @@
}
/*
- * Writes hex_len hex characters (1/2 byte) to hex from bytes.
- */
-std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
- std::string hex("0x");
- for (size_t i = 0; i < bytes_len; i++)
- android::base::StringAppendF(&hex, "%02x", bytes[i]);
- return hex;
-}
-
-/*
* Returns true is pathname is a directory
*/
bool is_dir(const char* pathname) {
diff --git a/init/util.h b/init/util.h
index 53f4547..2b57910 100644
--- a/init/util.h
+++ b/init/util.h
@@ -51,7 +51,6 @@
void import_kernel_cmdline(bool in_qemu,
const std::function<void(const std::string&, const std::string&, bool)>&);
bool make_dir(const std::string& path, mode_t mode);
-std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst);
diff --git a/liblog/tests/AndroidTest.xml b/liblog/tests/AndroidTest.xml
index 7b64433..c167478 100644
--- a/liblog/tests/AndroidTest.xml
+++ b/liblog/tests/AndroidTest.xml
@@ -16,6 +16,8 @@
<configuration description="Config for CTS Logging Library test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsLiblogTestCases->/data/local/tmp/CtsLiblogTestCases" />
diff --git a/libmeminfo/Android.bp b/libmeminfo/Android.bp
index 3e191ad..fc022bd 100644
--- a/libmeminfo/Android.bp
+++ b/libmeminfo/Android.bp
@@ -46,7 +46,6 @@
static_libs: [
"libmeminfo",
- "libpagemap",
"libbase",
"liblog",
],
diff --git a/libmeminfo/libdmabufinfo/Android.bp b/libmeminfo/libdmabufinfo/Android.bp
new file mode 100644
index 0000000..3d5f2e7
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/Android.bp
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2019 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.
+
+cc_defaults {
+ name: "dmabufinfo_defaults",
+ static_libs: [
+ "libbase",
+ "liblog",
+ "libprocinfo",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+cc_library_static {
+ name: "libdmabufinfo",
+ defaults: ["dmabufinfo_defaults"],
+ export_include_dirs: ["include"],
+ static_libs: ["libc++fs"],
+
+ srcs: [
+ "dmabufinfo.cpp",
+ ],
+}
+
+cc_test {
+ name: "dmabufinfo_test",
+ defaults: ["dmabufinfo_defaults"],
+ srcs: [
+ "dmabufinfo_test.cpp"
+ ],
+
+ static_libs: [
+ "libc++fs",
+ "libdmabufinfo",
+ "libion",
+ "libmeminfo",
+ ],
+}
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
new file mode 100644
index 0000000..41ecc51
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <dmabufinfo/dmabufinfo.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <filesystem>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <procinfo/process_map.h>
+
+namespace android {
+namespace dmabufinfo {
+
+static bool FileIsDmaBuf(const std::string& path) {
+ return ::android::base::StartsWith(path, "/dmabuf");
+}
+
+static bool ReadDmaBufFdInfo(pid_t pid, int fd, std::string* name, std::string* exporter,
+ uint64_t* count) {
+ std::string fdinfo = ::android::base::StringPrintf("/proc/%d/fdinfo/%d", pid, fd);
+ auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fdinfo.c_str(), "re"), fclose};
+ if (fp == nullptr) {
+ LOG(ERROR) << "Failed to open dmabuf info from debugfs";
+ return false;
+ }
+
+ char* line = nullptr;
+ size_t len = 0;
+ while (getline(&line, &len, fp.get()) > 0) {
+ switch (line[0]) {
+ case 'c':
+ if (strncmp(line, "count:", 6) == 0) {
+ char* c = line + 6;
+ *count = strtoull(c, nullptr, 10);
+ }
+ break;
+ case 'e':
+ if (strncmp(line, "exp_name:", 9) == 0) {
+ char* c = line + 9;
+ *exporter = ::android::base::Trim(c);
+ }
+ break;
+ case 'n':
+ if (strncmp(line, "name:", 5) == 0) {
+ char* c = line + 5;
+ *name = ::android::base::Trim(std::string(c));
+ }
+ break;
+ }
+ }
+
+ free(line);
+ return true;
+}
+
+static bool ReadDmaBufFdRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
+ std::string fdpath = ::android::base::StringPrintf("/proc/%d/fd", pid);
+ for (auto& de : std::filesystem::directory_iterator(fdpath)) {
+ if (!std::filesystem::is_symlink(de.path())) {
+ continue;
+ }
+
+ std::string target;
+ if (!::android::base::Readlink(de.path().string(), &target)) {
+ LOG(ERROR) << "Failed to find target for symlink: " << de.path().string();
+ return false;
+ }
+
+ if (!FileIsDmaBuf(target)) {
+ continue;
+ }
+
+ int fd;
+ if (!::android::base::ParseInt(de.path().filename().string(), &fd)) {
+ LOG(ERROR) << "Dmabuf fd: " << de.path().string() << " is invalid";
+ return false;
+ }
+
+ // Set defaults in case the kernel doesn't give us the information
+ // we need in fdinfo
+ std::string name = "<unknown>";
+ std::string exporter = "<unknown>";
+ uint64_t count = 0;
+ if (!ReadDmaBufFdInfo(pid, fd, &name, &exporter, &count)) {
+ LOG(ERROR) << "Failed to read fdinfo for: " << de.path().string();
+ return false;
+ }
+
+ struct stat sb;
+ if (stat(de.path().c_str(), &sb) < 0) {
+ PLOG(ERROR) << "Failed to stat: " << de.path().string();
+ return false;
+ }
+
+ DmaBuffer& buf =
+ dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
+ buf.AddFdRef(pid);
+ }
+
+ return true;
+}
+
+static bool ReadDmaBufMapRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
+ std::string mapspath = ::android::base::StringPrintf("/proc/%d/maps", pid);
+ auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(mapspath.c_str(), "re"), fclose};
+ if (fp == nullptr) {
+ LOG(ERROR) << "Failed to open maps for pid: " << pid;
+ return false;
+ }
+
+ char* line = nullptr;
+ size_t len = 0;
+
+ // Process the map if it is dmabuf. Add map reference to existing object in 'dmabufs'
+ // if it was already found. If it wasn't create a new one and append it to 'dmabufs'
+ auto account_dmabuf = [&](uint64_t start, uint64_t end, uint16_t /* flags */,
+ uint64_t /* pgoff */, const char* name) {
+ // no need to look into this mapping if it is not dmabuf
+ if (!FileIsDmaBuf(std::string(name))) {
+ return;
+ }
+
+ // TODO (b/123532375) : Add inode number to the callback of ReadMapFileContent.
+ //
+ // Workaround: we know 'name' points to the name at the end of 'line'.
+ // We use that to backtrack and pick up the inode number from the line as well.
+ // start end flag pgoff mj:mn inode name
+ // 00400000-00409000 r-xp 00000000 00:00 426998 /dmabuf (deleted)
+ const char* p = name;
+ p--;
+ // skip spaces
+ while (p != line && *p == ' ') {
+ p--;
+ }
+ // walk backwards to the beginning of inode number
+ while (p != line && isdigit(*p)) {
+ p--;
+ }
+ uint64_t inode = strtoull(p, nullptr, 10);
+ auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
+ [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
+ if (buf != dmabufs->end()) {
+ buf->AddMapRef(pid);
+ return;
+ }
+
+ // We have a new buffer, but unknown count and name
+ DmaBuffer& dbuf = dmabufs->emplace_back(inode, end - start, 0, "<unknown>", "<unknown>");
+ dbuf.AddMapRef(pid);
+ };
+
+ while (getline(&line, &len, fp.get()) > 0) {
+ if (!::android::procinfo::ReadMapFileContent(line, account_dmabuf)) {
+ LOG(ERROR) << "Failed t parse maps for pid: " << pid;
+ return false;
+ }
+ }
+
+ free(line);
+ return true;
+}
+
+// Public methods
+bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs, const std::string& path) {
+ auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+ if (fp == nullptr) {
+ LOG(ERROR) << "Failed to open dmabuf info from debugfs";
+ return false;
+ }
+
+ char* line = nullptr;
+ size_t len = 0;
+ dmabufs->clear();
+ while (getline(&line, &len, fp.get()) > 0) {
+ // The new dmabuf bufinfo format adds inode number and a name at the end
+ // We are looking for lines as follows:
+ // size flags mode count exp_name ino name
+ // 01048576 00000002 00000007 00000001 ion 00018758 CAMERA
+ // 01048576 00000002 00000007 00000001 ion 00018758
+ uint64_t size, count;
+ char* exporter_name = nullptr;
+ ino_t inode;
+ char* name = nullptr;
+ int matched = sscanf(line, "%" SCNu64 "%*x %*x %" SCNu64 " %ms %lu %ms", &size, &count,
+ &exporter_name, &inode, &name);
+ if (matched < 4) {
+ continue;
+ }
+ dmabufs->emplace_back(inode, size, count, exporter_name, matched > 4 ? name : "");
+ free(exporter_name);
+ free(name);
+ }
+
+ free(line);
+
+ return true;
+}
+
+bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
+ dmabufs->clear();
+ if (!ReadDmaBufFdRefs(pid, dmabufs)) {
+ LOG(ERROR) << "Failed to read dmabuf fd references";
+ return false;
+ }
+
+ if (!ReadDmaBufMapRefs(pid, dmabufs)) {
+ LOG(ERROR) << "Failed to read dmabuf map references";
+ return false;
+ }
+ return true;
+}
+
+} // namespace dmabufinfo
+} // namespace android
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
new file mode 100644
index 0000000..aa5f16c
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
@@ -0,0 +1,252 @@
+/* Copyright (C) 2019 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.
+ */
+
+#include <gtest/gtest.h>
+#include <linux/dma-buf.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <ion/ion.h>
+
+#include <dmabufinfo/dmabufinfo.h>
+
+using namespace ::android::dmabufinfo;
+using namespace ::android::base;
+
+#define MAX_HEAP_NAME 32
+#define ION_HEAP_ANY_MASK (0x7fffffff)
+
+struct ion_heap_data {
+ char name[MAX_HEAP_NAME];
+ __u32 type;
+ __u32 heap_id;
+ __u32 reserved0;
+ __u32 reserved1;
+ __u32 reserved2;
+};
+
+#ifndef DMA_BUF_SET_NAME
+#define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 5, const char*)
+#endif
+
+#define EXPECT_ONE_BUF_EQ(_bufptr, _name, _fdrefs, _maprefs, _expname, _count, _size) \
+ do { \
+ EXPECT_EQ(_bufptr->name(), _name); \
+ EXPECT_EQ(_bufptr->fdrefs().size(), _fdrefs); \
+ EXPECT_EQ(_bufptr->maprefs().size(), _maprefs); \
+ EXPECT_EQ(_bufptr->exporter(), _expname); \
+ EXPECT_EQ(_bufptr->count(), _count); \
+ EXPECT_EQ(_bufptr->size(), _size); \
+ } while (0)
+
+#define EXPECT_PID_IN_FDREFS(_bufptr, _pid, _expect) \
+ do { \
+ const std::vector<pid_t>& _fdrefs = _bufptr->fdrefs(); \
+ auto _ref = std::find_if(_fdrefs.begin(), _fdrefs.end(), \
+ [&](const pid_t& p) { return p == _pid; }); \
+ EXPECT_EQ((_ref == _fdrefs.end()), _expect); \
+ } while (0)
+
+#define EXPECT_PID_IN_MAPREFS(_bufptr, _pid, _expect) \
+ do { \
+ const std::vector<pid_t>& _maprefs = _bufptr->maprefs(); \
+ auto _ref = std::find_if(_maprefs.begin(), _maprefs.end(), \
+ [&](const pid_t& p) { return p == _pid; }); \
+ EXPECT_EQ((_ref == _maprefs.end()), _expect); \
+ } while (0)
+
+TEST(DmaBufInfoParser, TestReadDmaBufInfo) {
+ std::string bufinfo = R"bufinfo(00045056 00000002 00000007 00000002 ion 00022069
+ Attached Devices:
+Total 0 devices attached
+01048576 00000002 00000007 00000001 ion 00019834 CAMERA
+ Attached Devices:
+ soc:qcom,cam_smmu:msm_cam_smmu_icp
+Total 1 devices attached)bufinfo";
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(::android::base::WriteStringToFd(bufinfo, tf.fd));
+ std::string path = std::string(tf.path);
+
+ std::vector<DmaBuffer> dmabufs;
+ EXPECT_TRUE(ReadDmaBufInfo(&dmabufs, path));
+
+ EXPECT_EQ(dmabufs.size(), 2UL);
+
+ EXPECT_EQ(dmabufs[0].size(), 45056UL);
+ EXPECT_EQ(dmabufs[0].inode(), 22069UL);
+ EXPECT_EQ(dmabufs[0].count(), 2UL);
+ EXPECT_EQ(dmabufs[0].exporter(), "ion");
+ EXPECT_TRUE(dmabufs[0].name().empty());
+ EXPECT_EQ(dmabufs[0].total_refs(), 0ULL);
+ EXPECT_TRUE(dmabufs[0].fdrefs().empty());
+ EXPECT_TRUE(dmabufs[0].maprefs().empty());
+
+ EXPECT_EQ(dmabufs[1].size(), 1048576UL);
+ EXPECT_EQ(dmabufs[1].inode(), 19834UL);
+ EXPECT_EQ(dmabufs[1].count(), 1UL);
+ EXPECT_EQ(dmabufs[1].exporter(), "ion");
+ EXPECT_FALSE(dmabufs[1].name().empty());
+ EXPECT_EQ(dmabufs[1].name(), "CAMERA");
+ EXPECT_EQ(dmabufs[1].total_refs(), 0ULL);
+ EXPECT_TRUE(dmabufs[1].fdrefs().empty());
+ EXPECT_TRUE(dmabufs[1].maprefs().empty());
+}
+
+class DmaBufTester : public ::testing::Test {
+ public:
+ DmaBufTester() : ion_fd(ion_open()), ion_heap_mask(get_ion_heap_mask()) {}
+
+ ~DmaBufTester() {
+ if (is_valid()) {
+ ion_close(ion_fd);
+ }
+ }
+
+ bool is_valid() { return (ion_fd >= 0 && ion_heap_mask > 0); }
+
+ unique_fd allocate(uint64_t size, const std::string& name) {
+ int fd;
+ int err = ion_alloc_fd(ion_fd, size, 0, ion_heap_mask, 0, &fd);
+ if (err < 0) {
+ return unique_fd{err};
+ }
+
+ if (!name.empty()) {
+ err = ioctl(fd, DMA_BUF_SET_NAME, name.c_str());
+ if (err < 0) return unique_fd{-errno};
+ }
+
+ return unique_fd{fd};
+ }
+
+ private:
+ int get_ion_heap_mask() {
+ if (ion_fd < 0) {
+ return 0;
+ }
+
+ if (ion_is_legacy(ion_fd)) {
+ // Since ION is still in staging, we've seen that the heap mask ids are also
+ // changed across kernels for some reason. So, here we basically ask for a buffer
+ // from _any_ heap.
+ return ION_HEAP_ANY_MASK;
+ }
+
+ int cnt;
+ int err = ion_query_heap_cnt(ion_fd, &cnt);
+ if (err < 0) {
+ return err;
+ }
+
+ std::vector<ion_heap_data> heaps;
+ heaps.resize(cnt);
+ err = ion_query_get_heaps(ion_fd, cnt, &heaps[0]);
+ if (err < 0) {
+ return err;
+ }
+
+ unsigned int ret = 0;
+ for (auto& it : heaps) {
+ if (!strcmp(it.name, "ion_system_heap")) {
+ ret |= (1 << it.heap_id);
+ }
+ }
+
+ return ret;
+ }
+
+ unique_fd ion_fd;
+ const int ion_heap_mask;
+};
+
+TEST_F(DmaBufTester, TestFdRef) {
+ // Test if a dma buffer is found while the corresponding file descriptor
+ // is open
+ ASSERT_TRUE(is_valid());
+ pid_t pid = getpid();
+ std::vector<DmaBuffer> dmabufs;
+ {
+ // Allocate one buffer and make sure the library can see it
+ unique_fd buf = allocate(4096, "dmabuftester-4k");
+ ASSERT_GT(buf, 0) << "Allocated buffer is invalid";
+ ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
+
+ EXPECT_EQ(dmabufs.size(), 1UL);
+ EXPECT_ONE_BUF_EQ(dmabufs.begin(), "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL);
+
+ // Make sure the buffer has the right pid too.
+ EXPECT_PID_IN_FDREFS(dmabufs.begin(), pid, false);
+ }
+
+ // Now make sure the buffer has disappeared
+ ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
+ EXPECT_TRUE(dmabufs.empty());
+}
+
+TEST_F(DmaBufTester, TestMapRef) {
+ // Test to make sure we can find a buffer if the fd is closed but the buffer
+ // is mapped
+ ASSERT_TRUE(is_valid());
+ pid_t pid = getpid();
+ std::vector<DmaBuffer> dmabufs;
+ {
+ // Allocate one buffer and make sure the library can see it
+ unique_fd buf = allocate(4096, "dmabuftester-4k");
+ ASSERT_GT(buf, 0) << "Allocated buffer is invalid";
+ auto ptr = mmap(0, 4096, PROT_READ, MAP_SHARED, buf, 0);
+ ASSERT_NE(ptr, MAP_FAILED);
+ ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
+
+ EXPECT_EQ(dmabufs.size(), 1UL);
+ EXPECT_ONE_BUF_EQ(dmabufs.begin(), "dmabuftester-4k", 1UL, 1UL, "ion", 2UL, 4096ULL);
+
+ // Make sure the buffer has the right pid too.
+ EXPECT_PID_IN_FDREFS(dmabufs.begin(), pid, false);
+ EXPECT_PID_IN_MAPREFS(dmabufs.begin(), pid, false);
+
+ // close the file descriptor and re-read the stats
+ buf.reset(-1);
+ ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
+
+ EXPECT_EQ(dmabufs.size(), 1UL);
+ EXPECT_ONE_BUF_EQ(dmabufs.begin(), "<unknown>", 0UL, 1UL, "<unknown>", 0UL, 4096ULL);
+
+ EXPECT_PID_IN_FDREFS(dmabufs.begin(), pid, true);
+ EXPECT_PID_IN_MAPREFS(dmabufs.begin(), pid, false);
+
+ // unmap the bufer and lose all references
+ munmap(ptr, 4096);
+ }
+
+ // Now make sure the buffer has disappeared
+ ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
+ EXPECT_TRUE(dmabufs.empty());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::android::base::InitLogging(argv, android::base::StderrLogger);
+ return RUN_ALL_TESTS();
+}
diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
new file mode 100644
index 0000000..29ce4d0
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace dmabufinfo {
+
+struct DmaBuffer {
+ public:
+ DmaBuffer(ino_t inode, uint64_t size, uint64_t count, const std::string& exporter,
+ const std::string& name)
+ : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {}
+ ~DmaBuffer() = default;
+
+ // Adds one file descriptor reference for the given pid
+ void AddFdRef(pid_t pid) { fdrefs_.emplace_back(pid); }
+
+ // Adds one map reference for the given pid
+ void AddMapRef(pid_t pid) { maprefs_.emplace_back(pid); }
+
+ // Getters for each property
+ uint64_t size() { return size_; }
+ const std::vector<pid_t>& fdrefs() const { return fdrefs_; }
+ const std::vector<pid_t>& maprefs() const { return maprefs_; }
+ ino_t inode() const { return inode_; }
+ uint64_t total_refs() const { return fdrefs_.size() + maprefs_.size(); }
+ uint64_t count() const { return count_; };
+ const std::string& name() const { return name_; }
+ const std::string& exporter() const { return exporter_; }
+
+ private:
+ ino_t inode_;
+ uint64_t size_;
+ uint64_t count_;
+ std::string exporter_;
+ std::string name_;
+ std::vector<pid_t> fdrefs_;
+ std::vector<pid_t> maprefs_;
+};
+
+// Read and return current dma buf objects from
+// DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not
+// populated here and will return an empty vector.
+// Returns false if something went wrong with the function, true otherwise.
+bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs,
+ const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo");
+
+// Read and return dmabuf objects for a given process without the help
+// of DEBUGFS
+bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
+
+} // namespace dmabufinfo
+} // namespace android
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index ccc40d1..5451ca3 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -26,7 +26,6 @@
#include <meminfo/pageacct.h>
#include <meminfo/procmeminfo.h>
#include <meminfo/sysmeminfo.h>
-#include <pagemap/pagemap.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -37,239 +36,12 @@
pid_t pid = -1;
-class ValidateProcMemInfo : public ::testing::Test {
- protected:
- void SetUp() override {
- ASSERT_EQ(0, pm_kernel_create(&ker));
- ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
- proc_mem = new ProcMemInfo(pid);
- ASSERT_NE(proc_mem, nullptr);
- }
-
- void TearDown() override {
- delete proc_mem;
- pm_process_destroy(proc);
- pm_kernel_destroy(ker);
- }
-
- pm_kernel_t* ker;
- pm_process_t* proc;
- ProcMemInfo* proc_mem;
-};
-
-TEST_F(ValidateProcMemInfo, TestMapsSize) {
- const std::vector<Vma>& maps = proc_mem->Maps();
- ASSERT_FALSE(maps.empty()) << "Process " << getpid() << " maps are empty";
-}
-
-TEST_F(ValidateProcMemInfo, TestMapsEquality) {
- const std::vector<Vma>& maps = proc_mem->Maps();
- ASSERT_EQ(proc->num_maps, maps.size());
-
- for (size_t i = 0; i < maps.size(); ++i) {
- EXPECT_EQ(proc->maps[i]->start, maps[i].start);
- EXPECT_EQ(proc->maps[i]->end, maps[i].end);
- EXPECT_EQ(proc->maps[i]->offset, maps[i].offset);
- EXPECT_EQ(std::string(proc->maps[i]->name), maps[i].name);
- }
-}
-
-TEST_F(ValidateProcMemInfo, TestMaps) {
- const std::vector<Vma>& maps = proc_mem->Maps();
- ASSERT_FALSE(maps.empty());
- ASSERT_EQ(proc->num_maps, maps.size());
-
- pm_memusage_t map_usage, proc_usage;
- pm_memusage_zero(&map_usage);
- pm_memusage_zero(&proc_usage);
- for (size_t i = 0; i < maps.size(); i++) {
- ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
- EXPECT_EQ(map_usage.vss, maps[i].usage.vss) << "VSS mismatch for map: " << maps[i].name;
- EXPECT_EQ(map_usage.rss, maps[i].usage.rss) << "RSS mismatch for map: " << maps[i].name;
- EXPECT_EQ(map_usage.pss, maps[i].usage.pss) << "PSS mismatch for map: " << maps[i].name;
- EXPECT_EQ(map_usage.uss, maps[i].usage.uss) << "USS mismatch for map: " << maps[i].name;
- pm_memusage_add(&proc_usage, &map_usage);
- }
-
- EXPECT_EQ(proc_usage.vss, proc_mem->Usage().vss);
- EXPECT_EQ(proc_usage.rss, proc_mem->Usage().rss);
- EXPECT_EQ(proc_usage.pss, proc_mem->Usage().pss);
- EXPECT_EQ(proc_usage.uss, proc_mem->Usage().uss);
-}
-
-TEST_F(ValidateProcMemInfo, TestSwapUsage) {
- const std::vector<Vma>& maps = proc_mem->Maps();
- ASSERT_FALSE(maps.empty());
- ASSERT_EQ(proc->num_maps, maps.size());
-
- pm_memusage_t map_usage, proc_usage;
- pm_memusage_zero(&map_usage);
- pm_memusage_zero(&proc_usage);
- for (size_t i = 0; i < maps.size(); i++) {
- ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
- EXPECT_EQ(map_usage.swap, maps[i].usage.swap) << "SWAP mismatch for map: " << maps[i].name;
- pm_memusage_add(&proc_usage, &map_usage);
- }
-
- EXPECT_EQ(proc_usage.swap, proc_mem->Usage().swap);
-}
-
-TEST_F(ValidateProcMemInfo, TestSwapOffsets) {
- const MemUsage& proc_usage = proc_mem->Usage();
- const std::vector<uint16_t>& swap_offsets = proc_mem->SwapOffsets();
-
- EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
-}
-
-TEST_F(ValidateProcMemInfo, TestPageMap) {
- std::vector<uint64_t> pagemap;
-
- auto vma_callback = [&](const Vma& vma) {
- uint64_t* pmap_out;
- size_t len;
- ASSERT_EQ(0, pm_process_pagemap_range(proc, vma.start, vma.end, &pmap_out, &len));
- ASSERT_TRUE(proc_mem->PageMap(vma, &pagemap));
-
- EXPECT_EQ(len, ((vma.end - vma.start) / getpagesize()));
- for (size_t i = 0; i < len; i++) {
- EXPECT_EQ(pmap_out[i], pagemap[i]);
- }
- };
- ASSERT_TRUE(proc_mem->ForEachVma(vma_callback));
-}
-
-class ValidateProcMemInfoWss : public ::testing::Test {
- protected:
- void SetUp() override {
- ASSERT_EQ(0, pm_kernel_create(&ker));
- ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
- proc_mem = new ProcMemInfo(pid, true);
- ASSERT_NE(proc_mem, nullptr);
- }
-
- void TearDown() override {
- delete proc_mem;
- pm_process_destroy(proc);
- pm_kernel_destroy(ker);
- }
-
- pm_kernel_t* ker;
- pm_process_t* proc;
- ProcMemInfo* proc_mem;
-};
-
-TEST_F(ValidateProcMemInfoWss, TestWorkingTestReset) {
+TEST(ProcMemInfo, TestWorkingTestReset) {
// Expect reset to succeed
EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
}
-TEST_F(ValidateProcMemInfoWss, TestWssEquality) {
- // Read wss using libpagemap
- pm_memusage_t wss_pagemap;
- EXPECT_EQ(0, pm_process_workingset(proc, &wss_pagemap, 0));
-
- // Read wss using libmeminfo
- MemUsage wss = proc_mem->Wss();
-
- // compare
- EXPECT_EQ(wss_pagemap.rss, wss.rss);
- EXPECT_EQ(wss_pagemap.pss, wss.pss);
- EXPECT_EQ(wss_pagemap.uss, wss.uss);
-}
-
-class ValidatePageAcct : public ::testing::Test {
- protected:
- void SetUp() override {
- ASSERT_EQ(0, pm_kernel_create(&ker));
- ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
- }
-
- void TearDown() override {
- pm_process_destroy(proc);
- pm_kernel_destroy(ker);
- }
-
- pm_kernel_t* ker;
- pm_process_t* proc;
-};
-
-TEST_F(ValidatePageAcct, TestPageFlags) {
- PageAcct& pi = PageAcct::Instance();
- pi.InitPageAcct(false);
-
- uint64_t* pagemap;
- size_t num_pages;
- for (size_t i = 0; i < proc->num_maps; i++) {
- ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
- for (size_t j = 0; j < num_pages; j++) {
- if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
-
- uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
- uint64_t page_flags_pagemap, page_flags_meminfo;
-
- ASSERT_EQ(0, pm_kernel_flags(ker, pfn, &page_flags_pagemap));
- ASSERT_TRUE(pi.PageFlags(pfn, &page_flags_meminfo));
- // check if page flags equal
- EXPECT_EQ(page_flags_pagemap, page_flags_meminfo);
- }
- free(pagemap);
- }
-}
-
-TEST_F(ValidatePageAcct, TestPageCounts) {
- PageAcct& pi = PageAcct::Instance();
- pi.InitPageAcct(false);
-
- uint64_t* pagemap;
- size_t num_pages;
- for (size_t i = 0; i < proc->num_maps; i++) {
- ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
- for (size_t j = 0; j < num_pages; j++) {
- uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
- uint64_t map_count_pagemap, map_count_meminfo;
-
- ASSERT_EQ(0, pm_kernel_count(ker, pfn, &map_count_pagemap));
- ASSERT_TRUE(pi.PageMapCount(pfn, &map_count_meminfo));
- // check if map counts are equal
- EXPECT_EQ(map_count_pagemap, map_count_meminfo);
- }
- free(pagemap);
- }
-}
-
-TEST_F(ValidatePageAcct, TestPageIdle) {
- // skip the test if idle page tracking isn't enabled
- if (pm_kernel_init_page_idle(ker) != 0) {
- return;
- }
-
- PageAcct& pi = PageAcct::Instance();
- ASSERT_TRUE(pi.InitPageAcct(true));
-
- uint64_t* pagemap;
- size_t num_pages;
- for (size_t i = 0; i < proc->num_maps; i++) {
- ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
- for (size_t j = 0; j < num_pages; j++) {
- if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
- uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
-
- ASSERT_EQ(0, pm_kernel_mark_page_idle(ker, &pfn, 1));
- int idle_status_pagemap = pm_kernel_get_page_idle(ker, pfn);
- int idle_status_meminfo = pi.IsPageIdle(pfn);
- EXPECT_EQ(idle_status_pagemap, idle_status_meminfo);
- }
- free(pagemap);
- }
-}
-
-TEST(TestProcMemInfo, MapsEmpty) {
- ProcMemInfo proc_mem(pid);
- const std::vector<Vma>& maps = proc_mem.Maps();
- EXPECT_GT(maps.size(), 0);
-}
-
-TEST(TestProcMemInfo, UsageEmpty) {
+TEST(ProcMemInfo, UsageEmpty) {
// If we created the object for getting working set,
// the usage must be empty
ProcMemInfo proc_mem(pid, true);
@@ -281,7 +53,14 @@
EXPECT_EQ(usage.swap, 0);
}
-TEST(TestProcMemInfo, WssEmpty) {
+TEST(ProcMemInfo, MapsNotEmpty) {
+ // Make sure the process maps are never empty
+ ProcMemInfo proc_mem(pid);
+ const std::vector<Vma>& maps = proc_mem.Maps();
+ EXPECT_FALSE(maps.empty());
+}
+
+TEST(ProcMemInfo, WssEmpty) {
// If we created the object for getting usage,
// the working set must be empty
ProcMemInfo proc_mem(pid, false);
@@ -293,7 +72,7 @@
EXPECT_EQ(wss.swap, 0);
}
-TEST(TestProcMemInfo, SwapOffsetsEmpty) {
+TEST(ProcMemInfo, SwapOffsetsEmpty) {
// If we created the object for getting working set,
// the swap offsets must be empty
ProcMemInfo proc_mem(pid, true);
@@ -301,7 +80,10 @@
EXPECT_EQ(swap_offsets.size(), 0);
}
-TEST(TestProcMemInfo, IsSmapsSupportedTest) {
+TEST(ProcMemInfo, IsSmapsSupportedTest) {
+ // Get any pid and check if /proc/<pid>/smaps_rollup exists using the API.
+ // The API must return the appropriate value regardless of the after it succeeds
+ // once.
std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
bool supported = IsSmapsRollupSupported(pid);
EXPECT_EQ(!access(path.c_str(), F_OK | R_OK), supported);
@@ -310,7 +92,8 @@
EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
}
-TEST(TestProcMemInfo, SmapsOrRollupTest) {
+TEST(ProcMemInfo, SmapsOrRollupTest) {
+ // Make sure we can parse 'smaps_rollup' correctly
std::string rollup =
R"rollup(12c00000-7fe859e000 ---p 00000000 00:00 0 [rollup]
Rss: 331908 kB
@@ -342,8 +125,8 @@
EXPECT_EQ(stats.swap_pss, 442);
}
-TEST(TestProcMemInfo, SmapsOrRollupSmapsTest) {
- // This is a made up smaps for the test
+TEST(ProcMemInfo, SmapsOrRollupSmapsTest) {
+ // Make sure /proc/<pid>/smaps is parsed correctly
std::string smaps =
R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
Name: [anon:dalvik-main space (region space)]
@@ -382,8 +165,9 @@
EXPECT_EQ(stats.swap_pss, 70);
}
-TEST(TestProcMemInfo, SmapsOrRollupPssRollupTest) {
- // This is a made up smaps for the test
+TEST(ProcMemInfo, SmapsOrRollupPssRollupTest) {
+ // Make sure /proc/<pid>/smaps is parsed correctly
+ // to get the PSS
std::string smaps =
R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
Name: [anon:dalvik-main space (region space)]
@@ -417,7 +201,8 @@
EXPECT_EQ(pss, 2652);
}
-TEST(TestProcMemInfo, SmapsOrRollupPssSmapsTest) {
+TEST(ProcMemInfo, SmapsOrRollupPssSmapsTest) {
+ // Correctly parse smaps file to gather pss
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
@@ -426,7 +211,8 @@
EXPECT_EQ(pss, 19119);
}
-TEST(TestProcMemInfo, ForEachVmaFromFileTest) {
+TEST(ProcMemInfo, ForEachVmaFromFileTest) {
+ // Parse smaps file correctly to make callbacks for each virtual memory area (vma)
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
ProcMemInfo proc_mem(pid);
@@ -519,13 +305,14 @@
EXPECT_EQ(vmas[5].usage.swap_pss, 0);
}
-TEST(TestProcMemInfo, SmapsReturnTest) {
+TEST(ProcMemInfo, SmapsReturnTest) {
+ // Make sure Smaps() is never empty for any process
ProcMemInfo proc_mem(pid);
auto vmas = proc_mem.Smaps();
EXPECT_FALSE(vmas.empty());
}
-TEST(TestProcMemInfo, SmapsTest) {
+TEST(ProcMemInfo, SmapsTest) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
ProcMemInfo proc_mem(pid);
@@ -616,56 +403,7 @@
EXPECT_EQ(vmas[5].usage.swap_pss, 0);
}
-TEST(ValidateProcMemInfoFlags, TestPageFlags1) {
- // Create proc object using libpagemap
- pm_kernel_t* ker;
- ASSERT_EQ(0, pm_kernel_create(&ker));
- pm_process_t* proc;
- ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
-
- // count swapbacked pages using libpagemap
- pm_memusage_t proc_usage;
- pm_memusage_zero(&proc_usage);
- ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED),
- (1 << KPF_SWAPBACKED)));
-
- // Create ProcMemInfo that counts swapbacked pages
- ProcMemInfo proc_mem(pid, false, (1 << KPF_SWAPBACKED), (1 << KPF_SWAPBACKED));
-
- EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
- EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
- EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
- EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
-
- pm_process_destroy(proc);
- pm_kernel_destroy(ker);
-}
-
-TEST(ValidateProcMemInfoFlags, TestPageFlags2) {
- // Create proc object using libpagemap
- pm_kernel_t* ker;
- ASSERT_EQ(0, pm_kernel_create(&ker));
- pm_process_t* proc;
- ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
-
- // count non-swapbacked pages using libpagemap
- pm_memusage_t proc_usage;
- pm_memusage_zero(&proc_usage);
- ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED), 0));
-
- // Create ProcMemInfo that counts non-swapbacked pages
- ProcMemInfo proc_mem(pid, false, 0, (1 << KPF_SWAPBACKED));
-
- EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
- EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
- EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
- EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
-
- pm_process_destroy(proc);
- pm_kernel_destroy(ker);
-}
-
-TEST(SysMemInfoParser, TestSysMemInfoFile) {
+TEST(SysMemInfo, TestSysMemInfoFile) {
std::string meminfo = R"meminfo(MemTotal: 3019740 kB
MemFree: 1809728 kB
MemAvailable: 2546560 kB
@@ -733,7 +471,7 @@
EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
}
-TEST(SysMemInfoParser, TestEmptyFile) {
+TEST(SysMemInfo, TestEmptyFile) {
TemporaryFile tf;
std::string empty_string = "";
ASSERT_TRUE(tf.fd != -1);
@@ -744,7 +482,7 @@
EXPECT_EQ(mi.mem_total_kb(), 0);
}
-TEST(SysMemInfoParser, TestZramTotal) {
+TEST(SysMemInfo, TestZramTotal) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
SysMemInfo mi;
@@ -774,7 +512,7 @@
MEMINFO_COUNT
};
-TEST(SysMemInfoParser, TestZramWithTags) {
+TEST(SysMemInfo, TestZramWithTags) {
std::string meminfo = R"meminfo(MemTotal: 3019740 kB
MemFree: 1809728 kB
MemAvailable: 2546560 kB
@@ -849,7 +587,7 @@
EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
}
-TEST(SysMemInfoParser, TestVmallocInfoNoMemory) {
+TEST(SysMemInfo, TestVmallocInfoNoMemory) {
std::string vmallocinfo =
R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
@@ -864,7 +602,7 @@
EXPECT_EQ(ReadVmallocInfo(file), 0);
}
-TEST(SysMemInfoParser, TestVmallocInfoKernel) {
+TEST(SysMemInfo, TestVmallocInfoKernel) {
std::string vmallocinfo =
R"vmallocinfo(0x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
@@ -876,7 +614,7 @@
EXPECT_EQ(ReadVmallocInfo(file), getpagesize());
}
-TEST(SysMemInfoParser, TestVmallocInfoModule) {
+TEST(SysMemInfo, TestVmallocInfoModule) {
std::string vmallocinfo =
R"vmallocinfo(0x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
@@ -888,7 +626,7 @@
EXPECT_EQ(ReadVmallocInfo(file), 6 * getpagesize());
}
-TEST(SysMemInfoParser, TestVmallocInfoAll) {
+TEST(SysMemInfo, TestVmallocInfoAll) {
std::string vmallocinfo =
R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
@@ -907,11 +645,7 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- if (argc <= 1) {
- cerr << "Pid of a permanently sleeping process must be provided." << endl;
- exit(EXIT_FAILURE);
- }
::android::base::InitLogging(argv, android::base::StderrLogger);
- pid = std::stoi(std::string(argv[1]));
+ pid = getpid();
return RUN_ALL_TESTS();
}
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index 1d43775..268496f 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -6,6 +6,7 @@
},
srcs: [
+ "checksum.c",
"dhcpclient.c",
"dhcpmsg.c",
"ifc_utils.c",
diff --git a/libnetutils/checksum.c b/libnetutils/checksum.c
new file mode 100644
index 0000000..74b5fdd
--- /dev/null
+++ b/libnetutils/checksum.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2011 Daniel Drown
+ *
+ * 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.
+ *
+ * checksum.c - ipv4/ipv6 checksum calculation
+ */
+#include <netinet/icmp6.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include "netutils/checksum.h"
+
+/* function: ip_checksum_add
+ * adds data to a checksum. only known to work on little-endian hosts
+ * current - the current checksum (or 0 to start a new checksum)
+ * data - the data to add to the checksum
+ * len - length of data
+ */
+uint32_t ip_checksum_add(uint32_t current, const void* data, int len) {
+ uint32_t checksum = current;
+ int left = len;
+ const uint16_t* data_16 = data;
+
+ while (left > 1) {
+ checksum += *data_16;
+ data_16++;
+ left -= 2;
+ }
+ if (left) {
+ checksum += *(uint8_t*)data_16;
+ }
+
+ return checksum;
+}
+
+/* function: ip_checksum_fold
+ * folds a 32-bit partial checksum into 16 bits
+ * temp_sum - sum from ip_checksum_add
+ * returns: the folded checksum in network byte order
+ */
+uint16_t ip_checksum_fold(uint32_t temp_sum) {
+ while (temp_sum > 0xffff) {
+ temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
+ }
+ return temp_sum;
+}
+
+/* function: ip_checksum_finish
+ * folds and closes the checksum
+ * temp_sum - sum from ip_checksum_add
+ * returns: a header checksum value in network byte order
+ */
+uint16_t ip_checksum_finish(uint32_t temp_sum) {
+ return ~ip_checksum_fold(temp_sum);
+}
+
+/* function: ip_checksum
+ * combined ip_checksum_add and ip_checksum_finish
+ * data - data to checksum
+ * len - length of data
+ */
+uint16_t ip_checksum(const void* data, int len) {
+ // TODO: consider starting from 0xffff so the checksum of a buffer entirely consisting of zeros
+ // is correctly calculated as 0.
+ uint32_t temp_sum;
+
+ temp_sum = ip_checksum_add(0, data, len);
+ return ip_checksum_finish(temp_sum);
+}
+
+/* function: ipv6_pseudo_header_checksum
+ * calculate the pseudo header checksum for use in tcp/udp/icmp headers
+ * ip6 - the ipv6 header
+ * len - the transport length (transport header + payload)
+ * protocol - the transport layer protocol, can be different from ip6->ip6_nxt for fragments
+ */
+uint32_t ipv6_pseudo_header_checksum(const struct ip6_hdr* ip6, uint32_t len, uint8_t protocol) {
+ uint32_t checksum_len = htonl(len);
+ uint32_t checksum_next = htonl(protocol);
+
+ uint32_t current = 0;
+
+ current = ip_checksum_add(current, &(ip6->ip6_src), sizeof(struct in6_addr));
+ current = ip_checksum_add(current, &(ip6->ip6_dst), sizeof(struct in6_addr));
+ current = ip_checksum_add(current, &checksum_len, sizeof(checksum_len));
+ current = ip_checksum_add(current, &checksum_next, sizeof(checksum_next));
+
+ return current;
+}
+
+/* function: ipv4_pseudo_header_checksum
+ * calculate the pseudo header checksum for use in tcp/udp headers
+ * ip - the ipv4 header
+ * len - the transport length (transport header + payload)
+ */
+uint32_t ipv4_pseudo_header_checksum(const struct iphdr* ip, uint16_t len) {
+ uint16_t temp_protocol, temp_length;
+
+ temp_protocol = htons(ip->protocol);
+ temp_length = htons(len);
+
+ uint32_t current = 0;
+
+ current = ip_checksum_add(current, &(ip->saddr), sizeof(uint32_t));
+ current = ip_checksum_add(current, &(ip->daddr), sizeof(uint32_t));
+ current = ip_checksum_add(current, &temp_protocol, sizeof(uint16_t));
+ current = ip_checksum_add(current, &temp_length, sizeof(uint16_t));
+
+ return current;
+}
+
+/* function: ip_checksum_adjust
+ * calculates a new checksum given a previous checksum and the old and new pseudo-header checksums
+ * checksum - the header checksum in the original packet in network byte order
+ * old_hdr_sum - the pseudo-header checksum of the original packet
+ * new_hdr_sum - the pseudo-header checksum of the translated packet
+ * returns: the new header checksum in network byte order
+ */
+uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum) {
+ // Algorithm suggested in RFC 1624.
+ // http://tools.ietf.org/html/rfc1624#section-3
+ checksum = ~checksum;
+ uint16_t folded_sum = ip_checksum_fold(checksum + new_hdr_sum);
+ uint16_t folded_old = ip_checksum_fold(old_hdr_sum);
+ if (folded_sum > folded_old) {
+ return ~(folded_sum - folded_old);
+ } else {
+ return ~(folded_sum - folded_old - 1); // end-around borrow
+ }
+}
diff --git a/libnetutils/include/netutils/checksum.h b/libnetutils/include/netutils/checksum.h
new file mode 100644
index 0000000..868217c
--- /dev/null
+++ b/libnetutils/include/netutils/checksum.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Daniel Drown
+ *
+ * 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.
+ *
+ * checksum.h - checksum functions
+ */
+#ifndef __CHECKSUM_H__
+#define __CHECKSUM_H__
+
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <stdint.h>
+
+uint32_t ip_checksum_add(uint32_t current, const void* data, int len);
+uint16_t ip_checksum_finish(uint32_t temp_sum);
+uint16_t ip_checksum(const void* data, int len);
+
+uint32_t ipv6_pseudo_header_checksum(const struct ip6_hdr* ip6, uint32_t len, uint8_t protocol);
+uint32_t ipv4_pseudo_header_checksum(const struct iphdr* ip, uint16_t len);
+
+uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum);
+
+#endif /* __CHECKSUM_H__ */
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index f4788d7..ddda7fd 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -81,6 +81,12 @@
const std::vector<FrameData>& frames() { return frames_; }
+ std::vector<FrameData> ConsumeFrames() {
+ std::vector<FrameData> frames = std::move(frames_);
+ frames_.clear();
+ return frames;
+ }
+
std::string FormatFrame(size_t frame_num);
static std::string FormatFrame(const FrameData& frame, bool is32bit);
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 3f5b88b..19982d8 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -44,10 +44,10 @@
}
printf("ARM Unwind Information:\n");
+ uint64_t load_bias = elf->GetLoadBias();
for (const auto& entry : interface->pt_loads()) {
- uint64_t load_bias = entry.second.table_offset;
printf(" PC Range 0x%" PRIx64 " - 0x%" PRIx64 "\n", entry.second.offset + load_bias,
- entry.second.table_size + load_bias);
+ entry.second.offset + entry.second.table_size + load_bias);
for (auto pc : *interface) {
std::string name;
printf(" PC 0x%" PRIx64, pc + load_bias);
diff --git a/lmkd/libpsi/Android.bp b/lmkd/libpsi/Android.bp
new file mode 100644
index 0000000..8a97094
--- /dev/null
+++ b/lmkd/libpsi/Android.bp
@@ -0,0 +1,22 @@
+cc_library_headers {
+ name: "libpsi_headers",
+ export_include_dirs: ["include"],
+}
+
+cc_library {
+ name: "libpsi",
+ srcs: ["psi.c"],
+ shared_libs: [
+ "liblog"
+ ],
+ header_libs: [
+ "libpsi_headers",
+ ],
+ export_header_lib_headers: [
+ "libpsi_headers",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/lmkd/libpsi/OWNERS b/lmkd/libpsi/OWNERS
new file mode 100644
index 0000000..b15bb48
--- /dev/null
+++ b/lmkd/libpsi/OWNERS
@@ -0,0 +1 @@
+surenb@google.com
diff --git a/lmkd/libpsi/include/psi/psi.h b/lmkd/libpsi/include/psi/psi.h
new file mode 100644
index 0000000..cd49e8b
--- /dev/null
+++ b/lmkd/libpsi/include/psi/psi.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef __ANDROID_PSI_H__
+#define __ANDROID_PSI_H__
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+enum psi_stall_type {
+ PSI_SOME,
+ PSI_FULL,
+ PSI_TYPE_COUNT
+};
+
+/*
+ * Initializes psi monitor.
+ * stall_type, threshold_us and window_us are monitor parameters
+ * When successful, the function returns file descriptor that can
+ * be used with poll/epoll syscalls to wait for EPOLLPRI events.
+ * When unsuccessful, the function returns -1 and errno is set
+ * appropriately.
+ */
+int init_psi_monitor(enum psi_stall_type stall_type,
+ int threshold_us, int window_us);
+
+/*
+ * Registers psi monitor file descriptor fd on the epoll instance
+ * referred to by the file descriptor epollfd.
+ * data parameter will be associated with event's epoll_data.ptr
+ * member.
+ */
+int register_psi_monitor(int epollfd, int fd, void* data);
+
+/*
+ * Unregisters psi monitor file descriptor fd from the epoll instance
+ * referred to by the file descriptor epollfd.
+ */
+int unregister_psi_monitor(int epollfd, int fd);
+
+/*
+ * Destroys psi monitor.
+ * fd is the file descriptor returned by psi monitor initialization
+ * routine.
+ * Note that if user process exits without calling this routine
+ * kernel will destroy the monitor as its lifetime is linked to
+ * the file descriptor.
+ */
+void destroy_psi_monitor(int fd);
+
+__END_DECLS
+
+#endif // __ANDROID_PSI_H__
diff --git a/lmkd/libpsi/psi.c b/lmkd/libpsi/psi.c
new file mode 100644
index 0000000..f4d5d18
--- /dev/null
+++ b/lmkd/libpsi/psi.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "libpsi"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/epoll.h>
+
+#include <log/log.h>
+#include "psi/psi.h"
+
+#define PSI_MON_FILE_MEMORY "/proc/pressure/memory"
+
+static const char* stall_type_name[] = {
+ "some",
+ "full",
+};
+
+int init_psi_monitor(enum psi_stall_type stall_type,
+ int threshold_us, int window_us) {
+ int fd;
+ int res;
+ char buf[256];
+
+ fd = TEMP_FAILURE_RETRY(open(PSI_MON_FILE_MEMORY, O_WRONLY | O_CLOEXEC));
+ if (fd < 0) {
+ ALOGE("No kernel psi monitor support (errno=%d)", errno);
+ return -1;
+ }
+
+ switch (stall_type) {
+ case (PSI_SOME):
+ case (PSI_FULL):
+ res = snprintf(buf, sizeof(buf), "%s %d %d",
+ stall_type_name[stall_type], threshold_us, window_us);
+ break;
+ default:
+ ALOGE("Invalid psi stall type: %d", stall_type);
+ errno = EINVAL;
+ goto err;
+ }
+
+ if (res >= (ssize_t)sizeof(buf)) {
+ ALOGE("%s line overflow for psi stall type '%s'",
+ PSI_MON_FILE_MEMORY, stall_type_name[stall_type]);
+ errno = EINVAL;
+ goto err;
+ }
+
+ res = TEMP_FAILURE_RETRY(write(fd, buf, strlen(buf) + 1));
+ if (res < 0) {
+ ALOGE("%s write failed for psi stall type '%s'; errno=%d",
+ PSI_MON_FILE_MEMORY, stall_type_name[stall_type], errno);
+ goto err;
+ }
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
+
+int register_psi_monitor(int epollfd, int fd, void* data) {
+ int res;
+ struct epoll_event epev;
+
+ epev.events = EPOLLPRI;
+ epev.data.ptr = data;
+ res = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &epev);
+ if (res < 0) {
+ ALOGE("epoll_ctl for psi monitor failed; errno=%d", errno);
+ }
+ return res;
+}
+
+int unregister_psi_monitor(int epollfd, int fd) {
+ return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
+}
+
+void destroy_psi_monitor(int fd) {
+ if (fd >= 0) {
+ close(fd);
+ }
+}
diff --git a/logd/tests/AndroidTest.xml b/logd/tests/AndroidTest.xml
index 84f0764..9a18edb 100644
--- a/logd/tests/AndroidTest.xml
+++ b/logd/tests/AndroidTest.xml
@@ -16,6 +16,8 @@
<configuration description="Config for CTS Logging Daemon test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsLogdTestCases->/data/local/tmp/CtsLogdTestCases" />
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index f998ae2..a854e93 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -66,6 +66,7 @@
# This namespace exposes externally accessible libraries from the Runtime APEX.
###############################################################################
namespace.runtime.isolated = true
+namespace.runtime.visible = true
# Keep in sync with ld.config.txt in the com.android.runtime APEX.
namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 2699286..bc8568e 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -133,6 +133,7 @@
# This namespace exposes externally accessible libraries from the Runtime APEX.
###############################################################################
namespace.runtime.isolated = true
+namespace.runtime.visible = true
# Keep in sync with ld.config.txt in the com.android.runtime APEX.
namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index bd889d1..ae486ea 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -69,6 +69,7 @@
namespace.default.visible = true
namespace.default.link.runtime.shared_libs = libart.so:libartd.so
namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs += libnativebridge.so
namespace.default.link.runtime.shared_libs += libnativehelper.so
namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -83,6 +84,7 @@
# This namespace pulls in externally accessible libs from the Runtime APEX.
###############################################################################
namespace.runtime.isolated = true
+namespace.runtime.visible = true
# Keep in sync with the default namespace in the com.android.runtime APEX
# ld.config.txt.