Merge "init: delete code that sets ro.recovery_id"
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/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/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ded3678..26ce3b2 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) {}
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 4f6a8ce..0482f6c 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -787,35 +787,6 @@
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.
@@ -943,26 +914,11 @@
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 = fstab->file_contents_mode;
@@ -983,26 +939,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;
}
@@ -1028,10 +964,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/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index e87332f..1685e50 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -79,7 +79,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 88ecec0..100e076 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -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();
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/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/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/liblog/tests/AndroidTest.xml b/liblog/tests/AndroidTest.xml
index 7b64433..bee0497 100644
--- a/liblog/tests/AndroidTest.xml
+++ b/liblog/tests/AndroidTest.xml
@@ -16,6 +16,7 @@
<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" />
<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/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/logd/tests/AndroidTest.xml b/logd/tests/AndroidTest.xml
index 84f0764..1e71a73 100644
--- a/logd/tests/AndroidTest.xml
+++ b/logd/tests/AndroidTest.xml
@@ -16,6 +16,7 @@
<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" />
<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.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index d2c0f2e..c97baeb 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -63,6 +63,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